using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace EuropeEngulfed.NET
{
    class GameState
    {
        public const int MAX_UBOATS = 60;
        public const int MAX_UBOATS_IN_A_TURN = 8;
        public const int MAX_FLAK = 4;
        public const int MAX_FIGHTERS = 30;
        public const int MAX_ASW = 7;
        public const int MAX_BOMBERS = 30;
        public const int MAX_V1 = 30;
        public const int MAX_V2 = 30;

        private Dictionary<GameTurn.GameDate,Dictionary<GameTurn.GamePhase,Dictionary<GameTurn.GameSubPhase, List<Move>>>> listOfMoves;
        public enum Weather
        {
            Clear,
            LightMud,
            Mud,
            Snow
        }


        public enum ForcePoolAjustmentType
        {
            newBlockInForcePool,
            newSpecialActionInForcePool,
            specialActionRemoval,
        }

        public struct ForcePoolAdjustment
        {
            public GameTurn.GameDate gameDate;
            public MapInfo.CountryID country;
            public ForcePoolAjustmentType forcePoolAjustmentType;
            public Block blockToAdd;
            public ForcePoolAdjustment(GameTurn.GameDate gameDate, MapInfo.CountryID country, ForcePoolAjustmentType forcePoolAjustmentType, Block blockToAdd)
            {
                this.gameDate = gameDate;
                this.country = country;
                this.forcePoolAjustmentType = forcePoolAjustmentType;
                this.blockToAdd = blockToAdd;
            }
        };

        private static ForcePoolAdjustment[] forcePoolAdjustments = 
        {
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb40, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.Germany, 3)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb41, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteInfantryBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.Germany, ForcePoolAjustmentType.specialActionRemoval, null),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new InfantryBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new InfantryBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new InfantryBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new InfantryBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new InfantryBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new InfantryBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new CavalryBlock(MapInfo.CountryID.USSR, 3)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new CavalryBlock(MapInfo.CountryID.USSR, 3)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new CavalryBlock(MapInfo.CountryID.USSR, 3)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new ArmorBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new ArmorBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new ArmorBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new ArmorBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new ArmorBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new ArmorBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb42, MapInfo.CountryID.GreatBritain, ForcePoolAjustmentType.newBlockInForcePool, new InfantryBlock(MapInfo.CountryID.GreatBritain, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.USA, ForcePoolAjustmentType.newBlockInForcePool, new AirborneBlock(MapInfo.CountryID.USA, 3)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.USA, ForcePoolAjustmentType.newSpecialActionInForcePool, null),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteInfantryBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newSpecialActionInForcePool, null),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.GreatBritain, ForcePoolAjustmentType.newBlockInForcePool, new InfantryBlock(MapInfo.CountryID.GreatBritain, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.GreatBritain, ForcePoolAjustmentType.newBlockInForcePool, new ArmorBlock(MapInfo.CountryID.GreatBritain, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb43, MapInfo.CountryID.GreatBritain, ForcePoolAjustmentType.newBlockInForcePool, new AirborneBlock(MapInfo.CountryID.GreatBritain, 3)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.USA, ForcePoolAjustmentType.newBlockInForcePool, new AirborneBlock(MapInfo.CountryID.USA, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.USA, ForcePoolAjustmentType.newBlockInForcePool, new AirborneBlock(MapInfo.CountryID.USA, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.USA, ForcePoolAjustmentType.newSpecialActionInForcePool, null),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteInfantryBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new EliteInfantryBlock(MapInfo.CountryID.Germany, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 1)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 1)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 1)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.newBlockInForcePool, new MilitiaBlock(MapInfo.CountryID.Germany, 1)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.Germany, ForcePoolAjustmentType.specialActionRemoval, null),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.USSR, 4)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newSpecialActionInForcePool, null),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb44, MapInfo.CountryID.GreatBritain, ForcePoolAjustmentType.newBlockInForcePool, new AirborneBlock(MapInfo.CountryID.GreatBritain, 2)),
            new ForcePoolAdjustment(GameTurn.GameDate.JanFeb45, MapInfo.CountryID.USSR, ForcePoolAjustmentType.newBlockInForcePool, new EliteArmorBlock(MapInfo.CountryID.USSR, 4)),
        };

        private static PlayingPiece[] vichyFranceSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.VichyFrance, 2),
                new InfantryBlock(MapInfo.CountryID.VichyFrance, 2),
                new InfantryBlock(MapInfo.CountryID.VichyFrance, 2),
            };

        private static PlayingPiece[] belgiumSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Belgium, 3),
                new InfantryBlock(MapInfo.CountryID.Belgium, 2),
            };
        private static PlayingPiece[] denmarkSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Denmark, 1, 2),
            };
        private static PlayingPiece[] greeceSetup =
            {
                new InfantryBlock(MapInfo.CountryID.Greece, 3),
                new InfantryBlock(MapInfo.CountryID.Greece, 3),
                new InfantryBlock(MapInfo.CountryID.Greece, 3),
                new InfantryBlock(MapInfo.CountryID.Greece, 2),
            };
        private static PlayingPiece[] netherlandsSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Netherlands, 2),
            };
        private static PlayingPiece[] norwaySetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Norway, 2),
                new InfantryBlock(MapInfo.CountryID.Norway, 2),
            };
        private static PlayingPiece[] portugalSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Portugal, 3),
            };
        private static PlayingPiece[] spainSetup = 
            {
                new ArmorBlock(MapInfo.CountryID.Spain, 2),
                new InfantryBlock(MapInfo.CountryID.Spain, 3),
                new InfantryBlock(MapInfo.CountryID.Spain, 3),
                new InfantryBlock(MapInfo.CountryID.Spain, 3),
                new InfantryBlock(MapInfo.CountryID.Spain, 3),
                new InfantryBlock(MapInfo.CountryID.Spain, 2),
                new InfantryBlock(MapInfo.CountryID.Spain, 2),
                new InfantryBlock(MapInfo.CountryID.Spain, 2),
            };
        private static PlayingPiece[] swedenSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Sweden, 3),
                new InfantryBlock(MapInfo.CountryID.Sweden, 3),
                new InfantryBlock(MapInfo.CountryID.Sweden, 3),
                new InfantryBlock(MapInfo.CountryID.Sweden, 2),
                new InfantryBlock(MapInfo.CountryID.Sweden, 2),
            };
        private static PlayingPiece[] switzerlandSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Switzerland, 3),
                new InfantryBlock(MapInfo.CountryID.Switzerland, 3),
                new InfantryBlock(MapInfo.CountryID.Switzerland, 3),
                new InfantryBlock(MapInfo.CountryID.Switzerland, 3),
                new InfantryBlock(MapInfo.CountryID.Switzerland, 3),
            };
        private static PlayingPiece[] turkeySetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Turkey, 3),
                new InfantryBlock(MapInfo.CountryID.Turkey, 3),
                new InfantryBlock(MapInfo.CountryID.Turkey, 3),
                new InfantryBlock(MapInfo.CountryID.Turkey, 3),
                new InfantryBlock(MapInfo.CountryID.Turkey, 2),
                new InfantryBlock(MapInfo.CountryID.Turkey, 2),
                new CavalryBlock(MapInfo.CountryID.Turkey, 2),
            };
        private static PlayingPiece[] yugoslaviaSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Yugoslavia, 3),
                new InfantryBlock(MapInfo.CountryID.Yugoslavia, 3),
                new InfantryBlock(MapInfo.CountryID.Yugoslavia, 2),
                new InfantryBlock(MapInfo.CountryID.Yugoslavia, 2),
                new CavalryBlock(MapInfo.CountryID.Yugoslavia, 2),
            };
        private static PlayingPiece[] bulgariaSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Bulgaria, 2),
            };
        private static PlayingPiece[] finlandSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Finland, 3),
                new InfantryBlock(MapInfo.CountryID.Finland, 3),
                new InfantryBlock(MapInfo.CountryID.Finland, 3),
            };
        private static PlayingPiece[] hungarySetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Hungary, 2),
            };
        private static PlayingPiece[] rumaniaSetup = 
            {
                new InfantryBlock(MapInfo.CountryID.Rumania, 3),
                new InfantryBlock(MapInfo.CountryID.Rumania, 2),
                new InfantryBlock(MapInfo.CountryID.Rumania, 2),
            };

        private GameTurn currentGameTurn;
        private GameTurn.GameDate nextBritishFleetAllowed;
        private GameTurn.GameDate nextFrenchFleetAllowed;
        private GameTurn.GameDate nextItalianFleetAllowed;
        private GameTurn.GameDate nextRussianFleetAllowed;
        private GameTurn.GameDate nextGermanFleetAllowed;
        private GameTurn.GameDate nextUSFleetAllowed;
        private GameTurn.GameDate nextASWAllowed;
        private GameTurn.GameDate nextBritishFlakAllowed;
        private GameTurn.GameDate nextGermanFlakAllowed;
        private GameTurn.GameDate russianEmergencyConscriptionTaken;

        private Dictionary<MapInfo.CountryID, bool> countriesConquered;
        private Dictionary<MapInfo.CountryID, bool> countriesAtWar;
        private Dictionary<MapInfo.CountryID, bool> countriesJoinedAllies;

        private bool italianMoraleHasCollapsed = false;
        private bool italianHasSurrendered = false;
        private bool maginotLineHasBeenBreached = false;
        private bool vichyDeclared = false;
        private bool vichyFranceOffered = false;
        private bool enemyUnitsHaveBeenInGermany = false;
        private bool germanUnitHasUsedItalianSeaTransport = false;
        private bool ploestiRestrictionsInEffet = false;
        private bool germanyAndUSSRAtWarSinceBeginningOfTurn = false;
        private bool vichyFranceAtWarSinceBeginningOfTurn = false;
        private bool freefrench1944UnitsAddedToUSForcePool = false;
        private bool novgorodHasFallen = false;
        private bool leningradHasFallen = false;
        private bool alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942 = false;
        private int numSovietHeavyFortificationsBuild = 0;
        private MapInfo.CountryID lastAxisMinorToReceiveFreeStep;
        private int stratWarfareEffectOnGermanStratMoves = 0;
        private int operationOverlordEffectOnGermanStratMoves = 0;
        private int stratWarfareEffectOnWAlliesStratMoves = 0;
        public bool lastTurnOperationOverlordLaunched = false;

        private Weather currentWesternZoneWeather;
        private Weather currentEasternZoneWeather;
        private Weather currentSouthernZoneWeather;

        private uint numPolishSpecialActions = 0;
        private uint numTurkishSpecialActions = 0;
        private uint numSpanishSpecialActions = 0;
        private uint numYugoslaviaSpecialActions = 0;
        private uint numGermanSpecialActions = 0;
        private uint numItalianSpecialActions = 0;
        private uint numFrenchSpecialActions = 0;
        private uint numUKSpecialActions = 0;
        private uint numUSSRSpecialActions = 0;
        private uint numUSSpecialActions = 0;

        private int numFrenchStratMoves = 2;
        private int numBritishStratMoves = 4;
        private int numUSStratMoves = 4;
        private int numUSSRStratMoves = 5;
        private int numGermanStratMoves = 7;
        private int numItalianStratMoves = 2;

        //General Information Track Info
        private uint UBoatPoints;
        private uint ASWLevel;
        private uint germanFlakLevel;
        private uint germanFighterPoints;
        private uint germanBomberPoints;
        private uint westernAlliedFlakLevel;
        private uint westernAlliedFighterPoints;
        private uint westernAlliedBomberPoints;
        private uint V1RocketLevel;
        private uint V2RocketLevel;
        private int currentGermanWERPProduction = 0;
        private int currentItalianWERPProduction = 0;
        private int currentUKWERPProduction = 0;
        private int currentFrenchWERPProduction = 0;
        private int currentUSWERPProduction = 0;
        private int currentUSSRWERPProduction = 0;

        //Force Pools
        private ForcePool germanForcePool;
        private ForcePool frenchForcePool;
        private ForcePool britishForcePool;
        private ForcePool bulgariaForcePool;
        private ForcePool finlandForcePool;
        private ForcePool hungaryForcePool;
        private ForcePool rumaniaForcePool;
        private ForcePool italianForcePool;
        private ForcePool sovietForcePool;
        private ForcePool USForcePool;
        private ForcePool belgiumForcePool;
        private ForcePool denmarkForcePool;
        private ForcePool greeceForcePool;
        private ForcePool theNetherLandsForcePool;
        private ForcePool norwayForcePool;
        private ForcePool polandForcePool;
        private ForcePool portugalForcePool;
        private ForcePool spainForcePool;
        private ForcePool swedenForcePool;
        private ForcePool switzerlandForcePool;
        private ForcePool turkeyForcePool;
        private ForcePool yugolaviaForcePool;

        private List<RegionState> regions;

        public Dictionary<GameTurn.GameDate,Dictionary<GameTurn.GamePhase,Dictionary<GameTurn.GameSubPhase, List<Move>>>> ListOfMoves
        {
            get
            {
                return new Dictionary<GameTurn.GameDate, Dictionary<GameTurn.GamePhase, Dictionary<GameTurn.GameSubPhase, List<Move>>>>(listOfMoves);
            }
        }

        public bool MaginotBreached
        {
            get
            {
                return maginotLineHasBeenBreached;
            }
        }

        public bool VichyDeclared
        {
            get
            {
                return vichyDeclared;
            }

            set
            {
                vichyDeclared = value;
            }
        }

        public bool VichyFranceOffered
        {
            get
            {
                return vichyFranceOffered;
            }

            set
            {
                vichyFranceOffered = value;
            }
        }

        public bool EnemyUnitsHaveBeenInGermany
        {
            get
            {
                return enemyUnitsHaveBeenInGermany;
            }

            set
            {
                enemyUnitsHaveBeenInGermany = value;
            }
        }

        public bool GermanUnitHasUsedItalianSeaTransport
        {
            get
            {
                return germanUnitHasUsedItalianSeaTransport;
            }

            set
            {
                germanUnitHasUsedItalianSeaTransport = value;
            }
        }

        public bool PloestiRestrictionsInEffet
        {
            get
            {
                return ploestiRestrictionsInEffet;
            }

            set
            {
                ploestiRestrictionsInEffet = value;
            }
        }

        public bool GermanyAndUSSRAtWarSinceBeginningOfTurn
        {
            get
            {
                return germanyAndUSSRAtWarSinceBeginningOfTurn;
            }

            set
            {
                germanyAndUSSRAtWarSinceBeginningOfTurn = value;
            }
        }

        public bool VichyFranceAtWarSinceBeginningOfTurn
        {
            get
            {
                return vichyFranceAtWarSinceBeginningOfTurn;
            }

            set
            {
                vichyFranceAtWarSinceBeginningOfTurn = value;
            }
        }

        public bool Freefrench1944UnitsAddedToUSForcePool
        {
            get
            {
                return freefrench1944UnitsAddedToUSForcePool;
            }

            set
            {
                freefrench1944UnitsAddedToUSForcePool = value;
            }
        }

        public int StratWarfareEffectOnGermanStratMoves
        {
            get
            {
                return stratWarfareEffectOnGermanStratMoves;
            }

            set
            {
                stratWarfareEffectOnGermanStratMoves = value;
            }
        }

        public int OperationOverlordEffectOnGermanStratMoves
        {
            get
            {
                return operationOverlordEffectOnGermanStratMoves;
            }

            set
            {
                operationOverlordEffectOnGermanStratMoves = value;
            }
        }

        public int StratWarfareEffectOnWAlliesStratMoves
        {
            get
            {
                return stratWarfareEffectOnWAlliesStratMoves;
            }

            set
            {
                stratWarfareEffectOnWAlliesStratMoves = value;
            }
        }

        public bool LastTurnOperationOverlordLaunched
        {
            get
            {
                return lastTurnOperationOverlordLaunched;
            }

            set
            {
                lastTurnOperationOverlordLaunched = value;
            }
        }

        public bool NovgorodHasFallen
        {
            get
            {
                return novgorodHasFallen;
            }

            set
            {
                novgorodHasFallen = value;
            }
        }

        public bool LeningradHasFallen
        {
            get
            {
                return leningradHasFallen;
            }

            set
            {
                leningradHasFallen = value;
            }
        }

        public bool AlliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942
        {
            get
            {
                return alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942;
            }

            set
            {
                alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942 = value;
            }
        }

        public int SovietHeavyFortificationsBuilt
        {
            get
            {
                return numSovietHeavyFortificationsBuild;
            }

            set
            {
                numSovietHeavyFortificationsBuild = value;
            }
        }

        public MapInfo.CountryID LastAxisMinorToReceiveFreeStep
        {
            get
            {
                return lastAxisMinorToReceiveFreeStep;
            }

            set
            {
                lastAxisMinorToReceiveFreeStep = value;
            }
        }

        public Weather CurrentWesternZoneWeather
        {
            get
            {
                return currentWesternZoneWeather;
            }

            set
            {
                currentWesternZoneWeather = value;
            }
        }

        public Weather CurrentEasternZoneWeather
        {
            get
            {
                return currentEasternZoneWeather;
            }

            set
            {
                currentEasternZoneWeather = value;
            }
        }

        public Weather CurrentSouthernZoneWeather
        {
            get
            {
                return currentSouthernZoneWeather;
            }

            set
            {
                currentSouthernZoneWeather = value;
            }
        }

        public GameTurn CurrentGameTurn
        {
            get
            {
                return currentGameTurn;
            }
        }

        public uint UBOATPoints
        {
            get
            {
                return UBoatPoints;
            }

            set
            {
                if (value <= MAX_UBOATS)
                    UBoatPoints = value;
                else
                    throw new InvalidOperationException();
            }
        }

        public uint ASWLEVEL
        {
            get
            {
                return ASWLevel;
            }
        }

        public uint GermanFlakLevel
        {
            get
            {
                return germanFlakLevel;
            }
        }

        public uint GermanFighterPoints
        {
            get
            {
                return germanFighterPoints;
            }

            set
            {
                if (value <= MAX_FIGHTERS)
                    germanFighterPoints = value;
                else
                    throw new InvalidOperationException();
            }
        }

        public uint GermanBomberPoints
        {
            get
            {
                return germanBomberPoints;
            }

            set
            {
                if (value <= MAX_BOMBERS)
                    germanBomberPoints = value;
                else
                    throw new InvalidOperationException();
            }
        }

        public uint WesternAlliedFlakLevel
        {
            get
            {
                return westernAlliedFlakLevel;
            }
        }

        public uint WesternAlliedFighterPoints
        {
            get
            {
                return westernAlliedFighterPoints;
            }

            set
            {
                if (value <= MAX_FIGHTERS)
                    westernAlliedFighterPoints = value;
                else
                    throw new InvalidOperationException();
            }
        }

        public uint WesternAlliedBomberPoints
        {
            get
            {
                return westernAlliedBomberPoints;
            }

            set
            {
                if (value <= MAX_BOMBERS)
                    westernAlliedBomberPoints = value;
                else
                    throw new InvalidOperationException();
            }
        }

        public uint V1ROCKETLevel
        {
            get
            {
                return V1RocketLevel;
            }
            
            set
            {
                if (value <= MAX_V1)
                    V1RocketLevel = value;
                else
                    throw new InvalidOperationException();
            }
        }

        public uint V2ROCKETLevel
        {
            get
            {
                return V2RocketLevel;
            }

            set
            {
                if (value <= MAX_V2)
                    V2RocketLevel = value;
                else
                    throw new InvalidOperationException();
            }
        }

        public uint GermanSpecialActions
        {
            get
            {
                return numGermanSpecialActions;
            }
        }

        public uint ItalianSpecialActions
        {
            get
            {
                return numItalianSpecialActions;
            }
        }

        public bool ItalianMoraleHasCollapsed
        {
            get
            {
                return italianMoraleHasCollapsed;
            }

            set
            {
                italianMoraleHasCollapsed = value;
            }
        }

        public bool ItalianHasSurrendered
        {
            get
            {
                return italianHasSurrendered;
            }

            set
            {
                italianHasSurrendered = true;
            }
        }

        public GameTurn.GameDate NextGermanFleetAllowed
        {
            get
            {
                return nextGermanFleetAllowed;
            }
        }

        public GameTurn.GameDate NextItalianFleetAllowed
        {
            get
            {
                return nextItalianFleetAllowed;
            }
        }

        public GameTurn.GameDate NextGermanFlakAllowed
        {
            get
            {
                return nextGermanFlakAllowed;
            }
        }

        public GameTurn.GameDate NextUKFleetAllowed
        {
            get
            {
                return nextBritishFleetAllowed;
            }
        }

        public GameTurn.GameDate NextFrenchFleetAllowed
        {
            get
            {
                return nextFrenchFleetAllowed;
            }
        }

        public GameTurn.GameDate NextUSSRFleetAllowed
        {
            get
            {
                return nextRussianFleetAllowed;
            }
        }

        public GameTurn.GameDate NextUSAFleetAllowed
        {
            get
            {
                return nextUSFleetAllowed;
            }
        }

        public GameTurn.GameDate NextFlakAllowed
        {
            get
            {
                return nextBritishFlakAllowed;
            }
        }

        public GameTurn.GameDate NextASWAllowed
        {
            get
            {
                return nextASWAllowed;
            }
        }

        public GameTurn.GameDate RussianEmergencyConscriptionTaken
        {
            get
            {
                return russianEmergencyConscriptionTaken;
            }

            set
            {
                russianEmergencyConscriptionTaken = value;
            }
        }

        public bool RussianConscriptionHasBeenTaken
        {
            get
            {
                return russianEmergencyConscriptionTaken != GameTurn.GameDate.SepOct39;
            }
        }

        private void Initialize39CampaignForcePools()
        {
            germanForcePool = new ForcePool(MapInfo.CountryID.Germany);
            frenchForcePool = new ForcePool(MapInfo.CountryID.France);
            britishForcePool = new ForcePool(MapInfo.CountryID.GreatBritain);
            bulgariaForcePool= new ForcePool(MapInfo.CountryID.Bulgaria);
            finlandForcePool = new ForcePool(MapInfo.CountryID.Finland);
            hungaryForcePool = new ForcePool(MapInfo.CountryID.Hungary);
            rumaniaForcePool = new ForcePool(MapInfo.CountryID.Rumania);
            italianForcePool = new ForcePool(MapInfo.CountryID.Italy);
            sovietForcePool = new ForcePool(MapInfo.CountryID.USSR);
            USForcePool = new ForcePool(MapInfo.CountryID.USA);
            belgiumForcePool = new ForcePool(MapInfo.CountryID.Belgium);
            denmarkForcePool = new ForcePool(MapInfo.CountryID.Denmark);
            greeceForcePool = new ForcePool(MapInfo.CountryID.Greece);
            theNetherLandsForcePool = new ForcePool(MapInfo.CountryID.Netherlands);
            norwayForcePool = new ForcePool(MapInfo.CountryID.Norway);
            polandForcePool = new ForcePool(MapInfo.CountryID.Poland);
            portugalForcePool = new ForcePool(MapInfo.CountryID.Portugal);
            spainForcePool = new ForcePool(MapInfo.CountryID.Spain);
            swedenForcePool = new ForcePool(MapInfo.CountryID.Sweden);
            switzerlandForcePool = new ForcePool(MapInfo.CountryID.Switzerland);
            turkeyForcePool = new ForcePool(MapInfo.CountryID.Turkey);
            yugolaviaForcePool = new ForcePool(MapInfo.CountryID.Yugoslavia);

            germanForcePool.CreateBlocksInPool(MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 22);
            germanForcePool.CreateBlocksInPool(MapInfo.CountryID.Germany, Block.BlockType.infantry, 4, 23);
            germanForcePool.CreateBlocksInPool(MapInfo.CountryID.Germany, Block.BlockType.cavalry, 2, 1);
            germanForcePool.CreateBlocksInPool(MapInfo.CountryID.Germany, Block.BlockType.armor, 4, 10);
            germanForcePool.CreateBlocksInPool(MapInfo.CountryID.Germany, Block.BlockType.airborne, 2, 1);
            germanForcePool.CreateBlocksInPool(MapInfo.CountryID.Germany, Block.BlockType.airborne, 3, 1);
            germanForcePool.CreateSpecialActions(5);
            germanForcePool.CreateGSUInPool(MapInfo.CountryID.Germany,6);
            germanForcePool.CreateBeachHeads(1);

            italianForcePool.CreateBlocksInPool(MapInfo.CountryID.Italy, Block.BlockType.infantry, 2, 11);
            italianForcePool.CreateBlocksInPool(MapInfo.CountryID.Italy, Block.BlockType.infantry, 3, 5);
            italianForcePool.CreateBlocksInPool(MapInfo.CountryID.Italy, Block.BlockType.armor, 2, 2);
            italianForcePool.CreateBlocksInPool(MapInfo.CountryID.Italy, Block.BlockType.armor, 3, 1);
            italianForcePool.CreateBlocksInPool(MapInfo.CountryID.Italy, Block.BlockType.airborne, 2, 1);
            italianForcePool.CreateSpecialActions(1);
            italianForcePool.CreateGSUInPool(MapInfo.CountryID.Italy,2);

            rumaniaForcePool.CreateBlocksInPool(MapInfo.CountryID.Rumania, Block.BlockType.infantry, 2, 4);
            rumaniaForcePool.CreateBlocksInPool(MapInfo.CountryID.Rumania, Block.BlockType.infantry, 3, 1);
            rumaniaForcePool.CreateBlocksInPool(MapInfo.CountryID.Rumania, Block.BlockType.armor, 2, 1);
            finlandForcePool.CreateBlocksInPool(MapInfo.CountryID.Finland, Block.BlockType.infantry, 2, 1);
            finlandForcePool.CreateBlocksInPool(MapInfo.CountryID.Finland, Block.BlockType.infantry, 3, 3);
            finlandForcePool.CreateBlocksInPool(MapInfo.CountryID.Finland, Block.BlockType.infantry, 4, 1);
            hungaryForcePool.CreateBlocksInPool(MapInfo.CountryID.Hungary, Block.BlockType.infantry, 2, 3);
            hungaryForcePool.CreateBlocksInPool(MapInfo.CountryID.Hungary, Block.BlockType.infantry, 3, 1);
            bulgariaForcePool.CreateBlocksInPool(MapInfo.CountryID.Bulgaria, Block.BlockType.infantry, 2, 3);

            sovietForcePool.CreateBlocksInPool(MapInfo.CountryID.USSR, Block.BlockType.infantry, 2, 17);
            sovietForcePool.CreateBlocksInPool(MapInfo.CountryID.USSR, Block.BlockType.infantry, 3, 19);
            sovietForcePool.CreateBlocksInPool(MapInfo.CountryID.USSR, Block.BlockType.infantry, 4, 8);
            sovietForcePool.CreateBlocksInPool(MapInfo.CountryID.USSR, Block.BlockType.armor, 2, 2);
            sovietForcePool.CreateBlocksInPool(MapInfo.CountryID.USSR, Block.BlockType.armor, 3, 5);
            sovietForcePool.CreateBlocksInPool(MapInfo.CountryID.USSR, Block.BlockType.airborne, 2, 1);
            sovietForcePool.CreateBlocksInPool(MapInfo.CountryID.USSR, Block.BlockType.airborne, 3, 1);
            sovietForcePool.CreateSpecialActions(1);
            sovietForcePool.CreateGSUInPool(MapInfo.CountryID.USSR,4);
            sovietForcePool.CreateBeachHeads(1);

            britishForcePool.CreateBlocksInPool(MapInfo.CountryID.GreatBritain, Block.BlockType.militia, 1, 2);
            britishForcePool.CreateBlocksInPool(MapInfo.CountryID.GreatBritain, Block.BlockType.militia, 2, 2);
            britishForcePool.CreateBlocksInPool(MapInfo.CountryID.GreatBritain, Block.BlockType.infantry, 3, 7);
            britishForcePool.CreateBlocksInPool(MapInfo.CountryID.GreatBritain, Block.BlockType.infantry, 4, 4);
            britishForcePool.CreateBlocksInPool(MapInfo.CountryID.GreatBritain, Block.BlockType.armor, 3, 3);
            britishForcePool.CreateBlocksInPool(MapInfo.CountryID.GreatBritain, Block.BlockType.armor, 4, 1);
            britishForcePool.CreateSpecialActions(2);
            britishForcePool.CreateGSUInPool(MapInfo.CountryID.GreatBritain,3);
            britishForcePool.CreateBeachHeads(2);

            frenchForcePool.CreateBlocksInPool(MapInfo.CountryID.France, Block.BlockType.infantry, 2, 7);
            frenchForcePool.CreateBlocksInPool(MapInfo.CountryID.France, Block.BlockType.infantry, 3, 14);
            frenchForcePool.CreateBlocksInPool(MapInfo.CountryID.France, Block.BlockType.infantry, 4, 2);
            frenchForcePool.CreateBlocksInPool(MapInfo.CountryID.France, Block.BlockType.armor, 2, 2);
            frenchForcePool.CreateBlocksInPool(MapInfo.CountryID.France, Block.BlockType.armor, 3, 2);
            frenchForcePool.CreateSpecialActions(1);
            frenchForcePool.CreateGSUInPool(MapInfo.CountryID.France,2);

            USForcePool.CreateBlocksInPool(MapInfo.CountryID.USA, Block.BlockType.infantry, 3, 10);
            USForcePool.CreateBlocksInPool(MapInfo.CountryID.USA, Block.BlockType.infantry, 4, 6);
            USForcePool.CreateBlocksInPool(MapInfo.CountryID.USA, Block.BlockType.armor, 3, 4);
            USForcePool.CreateBlocksInPool(MapInfo.CountryID.USA, Block.BlockType.armor, 4, 4);
            USForcePool.CreateSpecialActions(1);
            USForcePool.CreateGSUInPool(MapInfo.CountryID.USA,4);

            belgiumForcePool.CreateBlocksInPool(MapInfo.CountryID.Belgium, Block.BlockType.infantry, 2, 1);
            belgiumForcePool.CreateBlocksInPool(MapInfo.CountryID.Belgium, Block.BlockType.infantry, 3, 1);
            denmarkForcePool.CreateBlocksInPool(MapInfo.CountryID.Denmark, Block.BlockType.infantry, 2, 1);
            greeceForcePool.CreateBlocksInPool(MapInfo.CountryID.Greece, Block.BlockType.infantry, 2, 1);
            greeceForcePool.CreateBlocksInPool(MapInfo.CountryID.Greece, Block.BlockType.infantry, 3, 3);
            theNetherLandsForcePool.CreateBlocksInPool(MapInfo.CountryID.Netherlands, Block.BlockType.infantry, 2, 1);
            norwayForcePool.CreateBlocksInPool(MapInfo.CountryID.Norway, Block.BlockType.infantry, 2, 2);
            portugalForcePool.CreateBlocksInPool(MapInfo.CountryID.Portugal, Block.BlockType.infantry, 3, 1);
            spainForcePool.CreateBlocksInPool(MapInfo.CountryID.Spain, Block.BlockType.infantry, 2, 3);
            spainForcePool.CreateBlocksInPool(MapInfo.CountryID.Spain, Block.BlockType.infantry, 3, 4);
            spainForcePool.CreateBlocksInPool(MapInfo.CountryID.Spain, Block.BlockType.armor, 2, 1);
            spainForcePool.CreateSpecialActions(1);
            swedenForcePool.CreateBlocksInPool(MapInfo.CountryID.Sweden, Block.BlockType.infantry, 3, 3);
            swedenForcePool.CreateBlocksInPool(MapInfo.CountryID.Sweden, Block.BlockType.infantry, 2, 2);
            switzerlandForcePool.CreateBlocksInPool(MapInfo.CountryID.Switzerland, Block.BlockType.infantry, 3, 5);
            turkeyForcePool.CreateBlocksInPool(MapInfo.CountryID.Turkey, Block.BlockType.infantry, 2, 2);
            turkeyForcePool.CreateBlocksInPool(MapInfo.CountryID.Turkey, Block.BlockType.infantry, 3, 4);
            turkeyForcePool.CreateBlocksInPool(MapInfo.CountryID.Turkey, Block.BlockType.cavalry, 2, 1);
            turkeyForcePool.CreateSpecialActions(1);
            yugolaviaForcePool.CreateBlocksInPool(MapInfo.CountryID.Yugoslavia, Block.BlockType.infantry, 2, 2);
            yugolaviaForcePool.CreateBlocksInPool(MapInfo.CountryID.Yugoslavia, Block.BlockType.infantry, 3, 2);
            yugolaviaForcePool.CreateBlocksInPool(MapInfo.CountryID.Yugoslavia, Block.BlockType.cavalry, 2, 1);
            yugolaviaForcePool.CreateSpecialActions(1);
            polandForcePool.CreateBlocksInPool(MapInfo.CountryID.Poland, Block.BlockType.infantry, 2, 3);
            polandForcePool.CreateBlocksInPool(MapInfo.CountryID.Poland, Block.BlockType.infantry, 3, 6);
            polandForcePool.CreateBlocksInPool(MapInfo.CountryID.Poland, Block.BlockType.cavalry, 2, 1);
            polandForcePool.CreateSpecialActions(1);

            germanForcePool.PoolFactoryLock = true;
            frenchForcePool.PoolFactoryLock = true;
            britishForcePool.PoolFactoryLock = true;
            bulgariaForcePool.PoolFactoryLock = true;
            finlandForcePool.PoolFactoryLock = true;
            hungaryForcePool.PoolFactoryLock = true;
            rumaniaForcePool.PoolFactoryLock = true;
            italianForcePool.PoolFactoryLock = true;
            sovietForcePool.PoolFactoryLock = true;
            USForcePool.PoolFactoryLock = true;
            belgiumForcePool.PoolFactoryLock = true;
            denmarkForcePool.PoolFactoryLock = true;
            greeceForcePool.PoolFactoryLock = true;
            theNetherLandsForcePool.PoolFactoryLock = true;
            norwayForcePool.PoolFactoryLock = true;
            polandForcePool.PoolFactoryLock = true;
            portugalForcePool.PoolFactoryLock = true;
            spainForcePool.PoolFactoryLock = true;
            swedenForcePool.PoolFactoryLock = true;
            switzerlandForcePool.PoolFactoryLock = true;
            turkeyForcePool.PoolFactoryLock = true;
            yugolaviaForcePool.PoolFactoryLock = true;

        }

        public GameState()
        {
            regions = new List<RegionState>();
            foreach(int regionID in Enum.GetValues(typeof(MapInfo.RegionID)))
            {
                if (MapInfo.IsLandRegion((MapInfo.RegionID)regionID))
                    regions.Add(new LandRegionState((MapInfo.RegionID)regionID));
                else if (MapInfo.IsSeaRegion((MapInfo.RegionID)regionID))
                    regions.Add(new SeaRegionState((MapInfo.RegionID)regionID));
            }

            currentGameTurn = new GameTurn();
            currentWesternZoneWeather = Weather.Clear;
            currentEasternZoneWeather = Weather.Clear;
            currentSouthernZoneWeather = Weather.Clear;
            UBoatPoints = 0;
            ASWLevel = 0;
            germanFlakLevel = 0;
            germanFighterPoints = 0;
            germanBomberPoints = 0;
            westernAlliedFlakLevel = 0;
            westernAlliedFighterPoints = 0;
            westernAlliedBomberPoints = 0;
            V1RocketLevel = 0;
            V2RocketLevel = 0;
            countriesAtWar = new Dictionary<MapInfo.CountryID, bool>();
            foreach(int countryID in Enum.GetValues(typeof(MapInfo.CountryID)))
            {
                countriesAtWar.Add((MapInfo.CountryID)countryID, false);
            }

            countriesConquered = new Dictionary<MapInfo.CountryID, bool>();
            foreach (int countryID in Enum.GetValues(typeof(MapInfo.CountryID)))
            {
                countriesConquered.Add((MapInfo.CountryID)countryID, false);
            }

            countriesJoinedAllies = new Dictionary<MapInfo.CountryID, bool>();
            countriesJoinedAllies.Add(MapInfo.CountryID.Portugal, false);
            countriesJoinedAllies.Add(MapInfo.CountryID.Denmark, true);
            countriesJoinedAllies.Add(MapInfo.CountryID.Norway, true);
            countriesJoinedAllies.Add(MapInfo.CountryID.Sweden, true);
            countriesJoinedAllies.Add(MapInfo.CountryID.Hungary, false);
            countriesJoinedAllies.Add(MapInfo.CountryID.Rumania, false);
            countriesJoinedAllies.Add(MapInfo.CountryID.Bulgaria, false);

            listOfMoves = new Dictionary<GameTurn.GameDate, Dictionary<GameTurn.GamePhase, Dictionary<GameTurn.GameSubPhase, List<Move>>>>();
        }

        private void SetupStartingPositions()
        {
            //Setup USSR
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.OnegaSwamps, MapInfo.CountryID.USSR, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Novgorod, MapInfo.CountryID.USSR, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Leningrad, MapInfo.CountryID.USSR, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Minsk, MapInfo.CountryID.USSR, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Minsk, MapInfo.CountryID.USSR, Block.BlockType.armor, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Moscow, MapInfo.CountryID.USSR, Block.BlockType.airborne, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.PripetMarshes, MapInfo.CountryID.USSR, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Kiev, MapInfo.CountryID.USSR, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Kiev, MapInfo.CountryID.USSR, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Kiev, MapInfo.CountryID.USSR, Block.BlockType.infantry, 3, 3);
            PlaceGSUFromPoolIntoLandRegion(MapInfo.RegionID.Kiev, MapInfo.CountryID.USSR);
            PlaceGSUFromPoolIntoLandRegion(MapInfo.RegionID.Kiev, MapInfo.CountryID.USSR);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.DneprRiverBend, MapInfo.CountryID.USSR, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.DneprRiverBend, MapInfo.CountryID.USSR, Block.BlockType.infantry, 2, 2);

            //Setup Poland
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Warsaw, MapInfo.CountryID.Poland, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Warsaw, MapInfo.CountryID.Poland, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Warsaw, MapInfo.CountryID.Poland, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Warsaw, MapInfo.CountryID.Poland, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.BrestLitovsk, MapInfo.CountryID.Poland, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Lublin, MapInfo.CountryID.Poland, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Lublin, MapInfo.CountryID.Poland, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Lodz, MapInfo.CountryID.Poland, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Lodz, MapInfo.CountryID.Poland, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Lodz, MapInfo.CountryID.Poland, Block.BlockType.cavalry, 2, 2);

            //Setup Italy
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Albania, MapInfo.CountryID.Italy, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Marmarica, MapInfo.CountryID.Italy, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Sicily, MapInfo.CountryID.Italy, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Calabria, MapInfo.CountryID.Italy, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Campania, MapInfo.CountryID.Italy, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Tuscany, MapInfo.CountryID.Italy, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Piedmont, MapInfo.CountryID.Italy, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Piedmont, MapInfo.CountryID.Italy, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Veneto, MapInfo.CountryID.Italy, Block.BlockType.infantry, 3, 3);

            //Setup France
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Lebanon, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Algiers, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Morocco, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Paris, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.FrenchAlps, MapInfo.CountryID.France, Block.BlockType.infantry, 2, 2);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.PaxDeCalais, MapInfo.CountryID.France, Block.BlockType.armor, 3, 3);
            PlaceGSUFromPoolIntoLandRegion(MapInfo.RegionID.PaxDeCalais, MapInfo.CountryID.France);

            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Metz, MapInfo.CountryID.France, Block.BlockType.infantry, 3, 3);

            //Setup Great Britain
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Alexandria, MapInfo.CountryID.GreatBritain, Block.BlockType.infantry, 4, 1);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.WesternEgypt, MapInfo.CountryID.GreatBritain, Block.BlockType.armor, 4, 1);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Gibraltar, MapInfo.CountryID.GreatBritain, Block.BlockType.infantry, 3, 1);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.London, MapInfo.CountryID.GreatBritain, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.London, MapInfo.CountryID.GreatBritain, Block.BlockType.infantry, 3, 1);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Southampton, MapInfo.CountryID.GreatBritain, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Southampton, MapInfo.CountryID.GreatBritain, Block.BlockType.infantry, 3, 1);
            PlaceGSUFromPoolIntoLandRegion(MapInfo.RegionID.Southampton, MapInfo.CountryID.GreatBritain);

            //SetupGermany
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.EastPrussia, MapInfo.CountryID.Germany, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.EastPrussia, MapInfo.CountryID.Germany, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.EastPrussia, MapInfo.CountryID.Germany, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Slovakia, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Slovakia, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Slovakia, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Silesia, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Silesia, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Silesia, MapInfo.CountryID.Germany, Block.BlockType.armor, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Silesia, MapInfo.CountryID.Germany, Block.BlockType.armor, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Silesia, MapInfo.CountryID.Germany, Block.BlockType.armor, 4, 4);
            PlaceGSUFromPoolIntoLandRegion(MapInfo.RegionID.Silesia, MapInfo.CountryID.Germany);
            PlaceGSUFromPoolIntoLandRegion(MapInfo.RegionID.Silesia, MapInfo.CountryID.Germany);
            PlaceGSUFromPoolIntoLandRegion(MapInfo.RegionID.Silesia, MapInfo.CountryID.Germany);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Baden, MapInfo.CountryID.Germany, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Baden, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Baden, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Baden, MapInfo.CountryID.Germany, Block.BlockType.airborne, 2, 1);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Baden, MapInfo.CountryID.Germany, Block.BlockType.airborne, 3, 1);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Rhineland, MapInfo.CountryID.Germany, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Rhineland, MapInfo.CountryID.Germany, Block.BlockType.infantry, 4, 4);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Rhineland, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Rhineland, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
            PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID.Rhineland, MapInfo.CountryID.Germany, Block.BlockType.infantry, 3, 3);
        }

        private void SetupStartingNavalPositions()
        {
            SeaRegionState seaRegionState = (SeaRegionState)GetRegionState(MapInfo.RegionID.BalticSea);
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.Germany));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.USSR));
            seaRegionState = (SeaRegionState)GetRegionState(MapInfo.RegionID.AtlanticOcean);
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.Germany));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.France));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.GreatBritain));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.GreatBritain));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.GreatBritain));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.GreatBritain));
            seaRegionState = (SeaRegionState)GetRegionState(MapInfo.RegionID.MediteraneanSea);
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.GreatBritain));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.GreatBritain));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.France));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.Italy));
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.Italy));
            seaRegionState = (SeaRegionState)GetRegionState(MapInfo.RegionID.BlackSea);
            seaRegionState.AddFleetPoint(new FleetPoint(MapInfo.CountryID.USSR));
        }

        private void InitializeRegionControl()
        {
            foreach(RegionState regionState in regions)
            {
                if(MapInfo.IsLandRegion(regionState.RegionID))
                {
                    ((LandRegionState)regionState).CountryControl = MapInfo.GetRegionOriginalCountryControl(regionState.RegionID);
                }
            }
        }

        private void InitializeNationsAtWar()
        {
            countriesAtWar[MapInfo.CountryID.Poland] = true;
            countriesAtWar[MapInfo.CountryID.Germany] = true;
            countriesAtWar[MapInfo.CountryID.France] = true;
            countriesAtWar[MapInfo.CountryID.GreatBritain] = true;
        }

        public bool IsNationAtWar(MapInfo.CountryID country)
        {
            return countriesAtWar[country];
        }

        public void SetNationAtWar(MapInfo.CountryID country)
        {
            countriesAtWar[country] = true;
        }

        public bool IsNationConquered(MapInfo.CountryID country)
        {
            return countriesConquered[country];
        }

        public void SetNationConquered(MapInfo.CountryID country)
        {
            countriesConquered[country] = true;
        }

        public void SetNationJoinAxis(MapInfo.CountryID country)
        {
            countriesJoinedAllies[country] = false;
        }

        public void SetNationJoinAllies(MapInfo.CountryID country)
        {
            countriesJoinedAllies[country] = true;
        }

        public void Setup39Campaign()
        {
            Initialize39CampaignForcePools();
            SetupStartingPositions();
            SetupStartingNavalPositions();
            InitializeRegionControl();
            InitializeNationsAtWar();
            UBoatPoints = 2;
            ASWLevel = 1;
            germanFighterPoints = 5;
            germanBomberPoints = 3;
            westernAlliedFlakLevel = 1;
            westernAlliedFighterPoints = 3;
            westernAlliedBomberPoints = 1;
            BuildSpecialAction(MapInfo.CountryID.Germany);
            BuildSpecialAction(MapInfo.CountryID.Germany);
            BuildSpecialAction(MapInfo.CountryID.Poland);

            nextBritishFleetAllowed = GameTurn.GameDate.SepOct39;
            nextFrenchFleetAllowed = GameTurn.GameDate.SepOct39;
            nextItalianFleetAllowed = GameTurn.GameDate.JanFeb40;
            nextRussianFleetAllowed = GameTurn.GameDate.SepOct39;
            nextGermanFleetAllowed = GameTurn.GameDate.JanFeb40;
            nextUSFleetAllowed = GameTurn.GameDate.SepOct39;
            nextASWAllowed = GameTurn.GameDate.SepOct39;
            nextBritishFlakAllowed = GameTurn.GameDate.SepOct39;
            nextGermanFlakAllowed = GameTurn.GameDate.SepOct39;
            lastAxisMinorToReceiveFreeStep = MapInfo.CountryID.Germany;
            russianEmergencyConscriptionTaken = GameTurn.GameDate.SepOct39;
        }

        public RegionState GetRegionState(MapInfo.RegionID regionID)
        {
            foreach(RegionState regionState in regions)
            {
                if (regionState.RegionID == regionID)
                    return regionState;
            }

            return null;
        }

        public ForcePool GetForcePoolForCountry(MapInfo.CountryID country)
        {
            switch(country)
            {
                case MapInfo.CountryID.Germany:
                    return germanForcePool;
                case MapInfo.CountryID.VichyFrance:
                case MapInfo.CountryID.France:
                    return frenchForcePool;
                case MapInfo.CountryID.GreatBritain:
                    return britishForcePool;
                case MapInfo.CountryID.Bulgaria:
                    return bulgariaForcePool;
                case MapInfo.CountryID.Finland:
                    return finlandForcePool;
                case MapInfo.CountryID.Hungary:
                    return hungaryForcePool;
                case MapInfo.CountryID.Rumania:
                    return rumaniaForcePool;
                case MapInfo.CountryID.Italy:
                    return italianForcePool;
                case MapInfo.CountryID.USSR:
                    return sovietForcePool;
                case MapInfo.CountryID.USA:
                    return USForcePool;
                case MapInfo.CountryID.Belgium:
                    return belgiumForcePool;
                case MapInfo.CountryID.Denmark:
                    return denmarkForcePool;
                case MapInfo.CountryID.Greece:
                    return greeceForcePool;
                case MapInfo.CountryID.Netherlands:
                    return theNetherLandsForcePool;
                case MapInfo.CountryID.Norway:
                    return norwayForcePool;
                case MapInfo.CountryID.Poland:
                    return polandForcePool;
                case MapInfo.CountryID.Portugal:
                    return portugalForcePool;
                case MapInfo.CountryID.Spain:
                    return spainForcePool;
                case MapInfo.CountryID.Sweden:
                    return swedenForcePool;
                case MapInfo.CountryID.Switzerland:
                    return switzerlandForcePool;
                case MapInfo.CountryID.Turkey:
                    return turkeyForcePool;
                case MapInfo.CountryID.Yugoslavia:
                    return yugolaviaForcePool;
                default:
                    throw (new Exception("Invalid country for force pool"));
            }
        }

        public List<PlayingPiece> GetCopiedListOfEEPlayingPiecesFromForcePool(MapInfo.CountryID country)
        {
            return GetForcePoolForCountry(country).GetCopyOfEuropeEngulfedPlayingPieces();
        }

        public bool PlaceBlockFromPoolIntoLandRegion(MapInfo.RegionID regionID,MapInfo.CountryID country, Block.BlockType blockType, uint maxStrength, uint currentStrength)
        {
            if(MapInfo.IsLandRegion(regionID))
            {
                LandRegionState landRegionState = (LandRegionState)GetRegionState(regionID);
                if (landRegionState != null)
                {
                    ForcePool forcepool;
                    if(country == MapInfo.CountryID.VichyFrance)
                        forcepool = GetForcePoolForCountry(MapInfo.CountryID.France);
                    else
                        forcepool = GetForcePoolForCountry(country);
                    Block blockToPlace = forcepool.GetBlock(country, blockType, maxStrength);
                    blockToPlace.CurrentStrength = currentStrength;
                    blockToPlace.OutOfSupplyState = PlayingPiece.OOSState.InSupply;
                    if(blockToPlace != null)
                    {
                        landRegionState.AddBlock(blockToPlace);
                        return true;
                    }
                }
            }
            else
                throw(new Exception("Attempted to put block in non-land region"));
            return false;
        }

        public bool PlaceGSUFromPoolIntoLandRegion(MapInfo.RegionID regionID, MapInfo.CountryID country)
        {
            if (MapInfo.IsLandRegion(regionID))
            {
                LandRegionState landRegionState = (LandRegionState)GetRegionState(regionID);
                if (landRegionState != null)
                {
                    ForcePool forcepool = GetForcePoolForCountry(country);
                    GroundSupportUnit GSUToPlace = forcepool.GetGSU(country);
                    if (GSUToPlace != null)
                    {
                        landRegionState.AddGSU(GSUToPlace);
                        return true;
                    }
                }
            }
            else
                throw (new Exception("Attempted to put GSU in non-land region"));
            return false;
        }

        public void ReturnPlayingPieceToForcePool(PlayingPiece playingPieceToReturn)
        {
            ForcePool forcePool = GetForcePoolForCountry(playingPieceToReturn.CountryOwner);
            if(playingPieceToReturn is Block)
            {
                forcePool.ReturnBlock((Block)playingPieceToReturn);
            }
            else if(playingPieceToReturn is GroundSupportUnit)
            {
                forcePool.ReturnGSU((GroundSupportUnit)playingPieceToReturn);
            }
        }

        public bool GameEnded()
        {
            return false;
        }

        public System.Collections.IEnumerator GetRegionStates()
        {
            return regions.GetEnumerator();
        }

        public void SetAllAxisPlayingPiecesAsSupplied()
        {
            foreach(RegionState EERegionState in regions)
            {
                if(MapInfo.IsLandRegion(EERegionState.RegionID))
                {
                    ((LandRegionState)EERegionState).SetAllAxisPlayingPiecesAsSupplied(this);
                }
            }
        }

        public void SetAllAxisPlayingPiecesAsUnSupplied()
        {
            foreach (RegionState EERegionState in regions)
            {
                EERegionState.SetAllAxisPlayingPiecesAsUnSupplied(this);
            }
        }

        public void SetAllAlliedPlayingPiecesAsSupplied()
        {
            foreach (RegionState EERegionState in regions)
            {
                if (MapInfo.IsLandRegion(EERegionState.RegionID))
                {
                    ((LandRegionState)EERegionState).SetAllAlliedPlayingPiecesAsSupplied(this);
                }
            }
        }

        public void SetAllAlliedPlayingPiecesAsUnSupplied()
        {
            foreach (RegionState EERegionState in regions)
            {
                EERegionState.SetAllAlliedPlayingPiecesAsUnSupplied(this);
            }
        }

        public bool IsAlliedCountry(MapInfo.CountryID countryID)
        {
            switch (countryID)
            {
                case MapInfo.CountryID.GreatBritain:
                case MapInfo.CountryID.France:
                case MapInfo.CountryID.FreeFrance:
                case MapInfo.CountryID.USA:
                case MapInfo.CountryID.USSR:
                case MapInfo.CountryID.Belgium:
                case MapInfo.CountryID.Netherlands:
                case MapInfo.CountryID.Spain:
                case MapInfo.CountryID.Sweden:
                case MapInfo.CountryID.Poland:
                case MapInfo.CountryID.Switzerland:
                case MapInfo.CountryID.Yugoslavia:
                case MapInfo.CountryID.Greece:
                case MapInfo.CountryID.Turkey:
                    return true;
                case MapInfo.CountryID.Germany:
                case MapInfo.CountryID.Italy:
                case MapInfo.CountryID.VichyFrance:
                case MapInfo.CountryID.Finland:
                case MapInfo.CountryID.BalticStates:
                    return false;
                default:
                    return countriesJoinedAllies[countryID];
            }
        }

        public bool IsAxisCountry(MapInfo.CountryID countryID)
        {
            switch (countryID)
            {
                case MapInfo.CountryID.Germany:
                case MapInfo.CountryID.Italy:
                case MapInfo.CountryID.VichyFrance:
                case MapInfo.CountryID.Finland:
                case MapInfo.CountryID.BalticStates:
                    return true;
                case MapInfo.CountryID.GreatBritain:
                case MapInfo.CountryID.France:
                case MapInfo.CountryID.USA:
                case MapInfo.CountryID.USSR:
                case MapInfo.CountryID.Belgium:
                case MapInfo.CountryID.Netherlands:
                case MapInfo.CountryID.Spain:
                case MapInfo.CountryID.Sweden:
                case MapInfo.CountryID.Poland:
                case MapInfo.CountryID.Switzerland:
                case MapInfo.CountryID.Yugoslavia:
                case MapInfo.CountryID.Greece:
                case MapInfo.CountryID.Turkey:
                case MapInfo.CountryID.FreeFrance:
                    return false;
                default:
                    return !countriesJoinedAllies[countryID];
            }
        }

        public int GetAxisSeaSupplyCapacity(MapInfo.RegionID seaRegionID)
        {
            //3.31 FLEET SUPPLY-CAPACITY: three units per Fleet Point for the Axis
            if (seaRegionID == MapInfo.RegionID.BalticSea || seaRegionID == MapInfo.RegionID.AtlanticOcean)
            {
                return ((SeaRegionState)GetRegionState(seaRegionID)).GetNumberOfAxisFleetPoints() * 3;
            }
            else if (seaRegionID == MapInfo.RegionID.MediteraneanSea)
            {
                //3.33 MEDITERRANEAN SUPPLY RESTRICTIONS
                LandRegionState maltaRegionState = (LandRegionState)GetRegionState(MapInfo.RegionID.Malta);
                LandRegionState sicilyRegionState = (LandRegionState)GetRegionState(MapInfo.RegionID.Sicily);
                LandRegionState sardiniaRegionState = (LandRegionState)GetRegionState(MapInfo.RegionID.Sardinia);

                if (countriesAtWar[MapInfo.CountryID.Italy] && (!IsAxisCountry(maltaRegionState.CountryControl) || !IsAxisCountry(sicilyRegionState.CountryControl) || !IsAxisCountry(sardiniaRegionState.CountryControl)))
                    return ((SeaRegionState)GetRegionState(seaRegionID)).GetNumberOfAxisFleetPoints() * 2;
                else
                    return ((SeaRegionState)GetRegionState(seaRegionID)).GetNumberOfAxisFleetPoints() * 3;
            }
            else
                return 0;
        }

        public int GetAlliedSeaSupplyCapacity(MapInfo.RegionID seaRegionID)
        {
            //3.31 FLEET SUPPLY-CAPACITY: four units per Fleet Point for France, Britain, and
            //the U.S.A., and three units per Fleet Point for the Axis
            //and the Soviets.
            if (seaRegionID == MapInfo.RegionID.BalticSea || seaRegionID == MapInfo.RegionID.BlackSea)
            {
                return ((SeaRegionState)GetRegionState(seaRegionID)).GetNumberOfAlliedFleetPoints() * 3;
            }
            else if(seaRegionID == MapInfo.RegionID.AtlanticOcean)
            {
                return ((SeaRegionState)GetRegionState(seaRegionID)).GetNumberOfAlliedFleetPoints() * 4;
            }
            else if (seaRegionID == MapInfo.RegionID.MediteraneanSea)
            {
                //3.33 MEDITERRANEAN SUPPLY RESTRICTIONS
                int supplyCapacityInMed = 4;
                LandRegionState maltaRegionState = (LandRegionState)GetRegionState(MapInfo.RegionID.Malta);
                LandRegionState sicilyRegionState = (LandRegionState)GetRegionState(MapInfo.RegionID.Sicily);
                LandRegionState sardiniaRegionState = (LandRegionState)GetRegionState(MapInfo.RegionID.Sardinia);
                LandRegionState creteRegionState = (LandRegionState)GetRegionState(MapInfo.RegionID.Crete);

                if (countriesAtWar[MapInfo.CountryID.Italy] && (IsAxisCountry(maltaRegionState.CountryControl) || IsAxisCountry(sicilyRegionState.CountryControl) || IsAxisCountry(sardiniaRegionState.CountryControl)))
                    supplyCapacityInMed--;
                if (IsAxisCountry(creteRegionState.CountryControl))
                    supplyCapacityInMed--;
                return ((SeaRegionState)GetRegionState(seaRegionID)).GetNumberOfAlliedFleetPoints() * supplyCapacityInMed;
            }
            else
                return 0;
        }

        public void AddMoveToListOfMoves(Move move)
        {
            if (!listOfMoves.ContainsKey(move.gameDate))
                listOfMoves.Add(move.gameDate, new Dictionary<GameTurn.GamePhase, Dictionary<GameTurn.GameSubPhase, List<Move>>>());
            if (!listOfMoves[move.gameDate].ContainsKey(move.gamePhase))
                listOfMoves[move.gameDate].Add(move.gamePhase, new Dictionary<GameTurn.GameSubPhase, List<Move>>());
            if (!listOfMoves[move.gameDate][move.gamePhase].ContainsKey(move.gameSubPhase))
                listOfMoves[move.gameDate][move.gamePhase].Add(move.gameSubPhase, new List<Move>());
            listOfMoves[move.gameDate][move.gamePhase][move.gameSubPhase].Add(move);
        }

        public void ProcessListOfMoves(List<Move> listOfMovesToProcess)
        {
            foreach (Move move in listOfMovesToProcess)
            {
                move.ProcessMoveAndAddToListOfMoves(this);
            }
        }

        public int CurrentGermanWERPs
        {
            get
            {
                return currentGermanWERPProduction;
            }

            set
            {
                currentGermanWERPProduction = value;
            }
        }

        public int CurrentItalianWERPs
        {
            get
            {
                return currentItalianWERPProduction;
            }

            set
            {
                currentItalianWERPProduction = value;
            }
        }

        public int CurrentUKWERPs
        {
            get
            {
                return currentUKWERPProduction;
            }

            set
            {
                currentUKWERPProduction = value;
            }
        }

        public int CurrentFrenchWERPs
        {
            get
            {
                return currentFrenchWERPProduction;
            }

            set
            {
                currentFrenchWERPProduction = value;
            }
        }

        public int CurrentUSSRWERPs
        {
            get
            {
                return currentUSSRWERPProduction;
            }

            set
            {
                currentUSSRWERPProduction = value;
            }
        }

        public int CurrentUSAWERPs
        {
            get
            {
                return currentUSWERPProduction;
            }

            set
            {
                currentUSWERPProduction = value;
            }
        }

        public void BuildASWLevel()
        {
            if (currentGameTurn.CurrentGameDate >= nextASWAllowed)
            {
                if (ASWLevel < MAX_ASW)
                    ASWLevel++;
                else
                    throw new InvalidOperationException();
               if(this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb40)
                    nextASWAllowed = GameTurn.GameDate.JanFeb40;
               else if(this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb41)
                    nextASWAllowed = GameTurn.GameDate.JanFeb41;
               else if(this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb42)
                    nextASWAllowed = GameTurn.GameDate.JanFeb42;
               else if(this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb43)
                    nextASWAllowed = GameTurn.GameDate.JanFeb43;
               else if(this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb44)
                   nextASWAllowed = GameTurn.GameDate.JanFeb44;
               else if(this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb45)
                   nextASWAllowed = GameTurn.GameDate.JanFeb45;
               else
                   nextASWAllowed = GameTurn.GameDate.JanFeb46;
            }
            else
                throw new InvalidOperationException();
        }

        public void BuildGermanFlakLevel()
        {
            if (currentGameTurn.CurrentGameDate >= nextGermanFlakAllowed)
            {
                if (germanFlakLevel < MAX_FLAK)
                    germanFlakLevel++;
                else
                    throw new InvalidOperationException();
                if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb40)
                    nextGermanFlakAllowed = GameTurn.GameDate.JanFeb40;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb41)
                    nextGermanFlakAllowed = GameTurn.GameDate.JanFeb41;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb42)
                    nextGermanFlakAllowed = GameTurn.GameDate.JanFeb42;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb43)
                    nextGermanFlakAllowed = GameTurn.GameDate.JanFeb43;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb44)
                    nextGermanFlakAllowed = GameTurn.GameDate.JanFeb44;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb45)
                    nextGermanFlakAllowed = GameTurn.GameDate.JanFeb45;
                else
                    nextGermanFlakAllowed = GameTurn.GameDate.JanFeb46;
            }
            else
                throw new InvalidOperationException();
        }

        public void BuildBritishFlakLevel()
        {
            if (currentGameTurn.CurrentGameDate >= nextBritishFlakAllowed)
            {
                if (ASWLevel < MAX_ASW)
                    westernAlliedFlakLevel++;
                else
                    throw new InvalidOperationException();
                if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb40)
                    nextBritishFlakAllowed = GameTurn.GameDate.JanFeb40;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb41)
                    nextBritishFlakAllowed = GameTurn.GameDate.JanFeb41;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb42)
                    nextBritishFlakAllowed = GameTurn.GameDate.JanFeb42;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb43)
                    nextBritishFlakAllowed = GameTurn.GameDate.JanFeb43;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb44)
                    nextBritishFlakAllowed = GameTurn.GameDate.JanFeb44;
                else if (this.currentGameTurn.CurrentGameDate < GameTurn.GameDate.JanFeb45)
                    nextBritishFlakAllowed = GameTurn.GameDate.JanFeb45;
                else
                    nextBritishFlakAllowed = GameTurn.GameDate.JanFeb46;
            }
            else
                throw new InvalidOperationException();
        }

        public void BuildFleetPoint(MapInfo.RegionID seaRegionID, MapInfo.CountryID countryID)
        {
            SeaRegionState seaRegionState = (SeaRegionState)this.GetRegionState(seaRegionID);
            bool validBuild = false;
           
            switch(countryID)
            {
                case MapInfo.CountryID.GreatBritain:
                    if(this.currentGameTurn.CurrentGameDate >= nextBritishFleetAllowed)
                    {
                        validBuild = true;
                        if (nextBritishFleetAllowed >= GameTurn.GameDate.SepOct45)
                            nextBritishFleetAllowed = GameTurn.GameDate.JanFeb46;
                        else
                        {
                            nextBritishFleetAllowed = this.currentGameTurn.CurrentGameDate;
                            nextBritishFleetAllowed++;
                            nextBritishFleetAllowed++;
                        }
                    }
                    break;
                case MapInfo.CountryID.France:
                    if (this.currentGameTurn.CurrentGameDate >= nextFrenchFleetAllowed)
                    {
                        validBuild = true;
                        if (nextFrenchFleetAllowed >= GameTurn.GameDate.SepOct45)
                            nextFrenchFleetAllowed = GameTurn.GameDate.JanFeb46;
                        else
                        {
                            nextFrenchFleetAllowed = this.currentGameTurn.CurrentGameDate;
                            nextFrenchFleetAllowed++;
                            nextFrenchFleetAllowed++;
                        }
                    }
                    break;
                case MapInfo.CountryID.USA:
                    if (this.currentGameTurn.CurrentGameDate >= nextUSFleetAllowed)
                    {
                        validBuild = true;
                        if (nextUSFleetAllowed >= GameTurn.GameDate.SepOct45)
                            nextUSFleetAllowed = GameTurn.GameDate.JanFeb46;
                        else
                        {
                            nextUSFleetAllowed = this.currentGameTurn.CurrentGameDate;
                            nextUSFleetAllowed++;
                            nextUSFleetAllowed++;
                        }
                    }
                    break;
                case MapInfo.CountryID.Germany:
                    if (this.currentGameTurn.CurrentGameDate >= nextGermanFleetAllowed)
                    {
                        validBuild = true;
                        if(this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb40 &&
                            this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec40)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec40)
                                nextGermanFleetAllowed = GameTurn.GameDate.MarApr41;
                            else
                                nextGermanFleetAllowed = GameTurn.GameDate.JanFeb41;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb41 &&
                            this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec41)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec41)
                                nextGermanFleetAllowed = GameTurn.GameDate.MarApr42;
                            else
                                nextGermanFleetAllowed = GameTurn.GameDate.JanFeb42;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb42 &&
                       this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec42)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec42)
                                nextGermanFleetAllowed = GameTurn.GameDate.MarApr43;
                            else
                                nextGermanFleetAllowed = GameTurn.GameDate.JanFeb43;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb43 &&
                       this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec43)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec43)
                                nextGermanFleetAllowed = GameTurn.GameDate.MarApr44;
                            else
                                nextGermanFleetAllowed = GameTurn.GameDate.JanFeb44;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb44 &&
                           this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec44)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec44)
                                nextGermanFleetAllowed = GameTurn.GameDate.MarApr45;
                            else
                                nextGermanFleetAllowed = GameTurn.GameDate.JanFeb45;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb45 &&
                                this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec45)
                        {
                            nextGermanFleetAllowed = GameTurn.GameDate.JanFeb46;
                        }
                    }
                    break;
                case MapInfo.CountryID.Italy:
                    if (this.currentGameTurn.CurrentGameDate >= nextItalianFleetAllowed)
                    {
                        validBuild = true;
                        if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb40 &&
                            this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec40)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec40)
                                nextItalianFleetAllowed = GameTurn.GameDate.MarApr41;
                            else
                                nextItalianFleetAllowed = GameTurn.GameDate.JanFeb41;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb41 &&
                            this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec41)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec41)
                                nextItalianFleetAllowed = GameTurn.GameDate.MarApr42;
                            else
                                nextItalianFleetAllowed = GameTurn.GameDate.JanFeb42;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb42 &&
                       this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec42)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec42)
                                nextItalianFleetAllowed = GameTurn.GameDate.MarApr43;
                            else
                                nextItalianFleetAllowed = GameTurn.GameDate.JanFeb43;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb43 &&
                                this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec43)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec43)
                                nextItalianFleetAllowed = GameTurn.GameDate.MarApr44;
                            else
                                nextItalianFleetAllowed = GameTurn.GameDate.JanFeb44;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb44 &&
                                this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec44)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec44)
                                nextItalianFleetAllowed = GameTurn.GameDate.MarApr45;
                            else
                                nextItalianFleetAllowed = GameTurn.GameDate.JanFeb45;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb45 &&
                                this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec45)
                        {
                            nextItalianFleetAllowed = GameTurn.GameDate.JanFeb46;
                        }
                    }
                    break;
                case MapInfo.CountryID.USSR:
                    if (this.currentGameTurn.CurrentGameDate >= nextRussianFleetAllowed)
                    {
                        validBuild = true;
                        if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.SepOct39)
                        {
                            nextRussianFleetAllowed = GameTurn.GameDate.JanFeb40;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb40 &&
                            this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec40)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec40)
                                nextRussianFleetAllowed = GameTurn.GameDate.MarApr41;
                            else
                                nextRussianFleetAllowed = GameTurn.GameDate.JanFeb41;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb41 &&
                                this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec41)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec41)
                                nextRussianFleetAllowed = GameTurn.GameDate.MarApr42;
                            else
                                nextRussianFleetAllowed = GameTurn.GameDate.JanFeb42;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb42 &&
                                this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec42)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec42)
                                nextRussianFleetAllowed = GameTurn.GameDate.MarApr43;
                            else
                                nextRussianFleetAllowed = GameTurn.GameDate.JanFeb43;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb43 &&
                                this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec43)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec43)
                                nextRussianFleetAllowed = GameTurn.GameDate.MarApr44;
                            else
                                nextRussianFleetAllowed = GameTurn.GameDate.JanFeb44;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb44 &&
                                this.currentGameTurn.CurrentGameDate <= GameTurn.GameDate.NovDec44)
                        {
                            if (this.currentGameTurn.CurrentGameDate == GameTurn.GameDate.NovDec44)
                                nextRussianFleetAllowed = GameTurn.GameDate.MarApr45;
                            else
                                nextRussianFleetAllowed = GameTurn.GameDate.JanFeb45;
                        }
                        else if (this.currentGameTurn.CurrentGameDate >= GameTurn.GameDate.JanFeb45 &&
                            nextRussianFleetAllowed <= GameTurn.GameDate.NovDec45)
                        {
                            nextRussianFleetAllowed = GameTurn.GameDate.JanFeb46;
                        }
                    }
                    break;
            }
            if (validBuild)
                seaRegionState.AddFleetPoint(new FleetPoint(countryID));
            else
                throw new InvalidOperationException();
        }

        public void BuildSpecialAction(MapInfo.CountryID country)
        {
            switch(country)
            {
                case MapInfo.CountryID.Poland:
                    if (polandForcePool.GetSpecialAction())
                        numPolishSpecialActions++;
                    break;
                case MapInfo.CountryID.Yugoslavia:
                    if (yugolaviaForcePool.GetSpecialAction())
                        numYugoslaviaSpecialActions++;
                    break;
                case MapInfo.CountryID.Spain:
                    if (spainForcePool.GetSpecialAction())
                        numSpanishSpecialActions++;
                    break;
                case MapInfo.CountryID.Turkey:
                    if (turkeyForcePool.GetSpecialAction())
                        numTurkishSpecialActions++;
                    break;
                case MapInfo.CountryID.Germany:
                    if (germanForcePool.GetSpecialAction())
                        numGermanSpecialActions++;
                    break;
                case MapInfo.CountryID.Italy:
                    if (italianForcePool.GetSpecialAction())
                        numItalianSpecialActions++;
                    break;
                case MapInfo.CountryID.France:
                    if (frenchForcePool.GetSpecialAction())
                        numFrenchSpecialActions++;
                    break;
                case MapInfo.CountryID.GreatBritain:
                    if (britishForcePool.GetSpecialAction())
                        numUKSpecialActions++;
                    break;
                case MapInfo.CountryID.USSR:
                    if (sovietForcePool.GetSpecialAction())
                        numUSSRSpecialActions++;
                    break;
                case MapInfo.CountryID.USA:
                    if (USForcePool.GetSpecialAction())
                        numUSSpecialActions++;
                    break;
                default:
                    throw new ArgumentException();
            }
        }

        public void SpendSpecialAction(MapInfo.CountryID country)
        {
            switch (country)
            {
                case MapInfo.CountryID.Poland:
                    if (numPolishSpecialActions > 0)
                    {
                        polandForcePool.ReturnSpecialAction();
                        numPolishSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.Yugoslavia:
                    if (numYugoslaviaSpecialActions > 0)
                    {
                        yugolaviaForcePool.ReturnSpecialAction();
                        numYugoslaviaSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.Spain:
                    if (numSpanishSpecialActions > 0)
                    {
                        spainForcePool.ReturnSpecialAction();
                        numSpanishSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.Turkey:
                    if (numTurkishSpecialActions > 0)
                    {
                        turkeyForcePool.ReturnSpecialAction();
                        numTurkishSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.Germany:
                    if (numGermanSpecialActions > 0)
                    {
                        germanForcePool.ReturnSpecialAction();
                        numGermanSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.Italy:
                    if (numItalianSpecialActions > 0)
                    {
                        italianForcePool.ReturnSpecialAction();
                        numItalianSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.France:
                    if (numFrenchSpecialActions > 0)
                    {
                        frenchForcePool.ReturnSpecialAction();
                        numFrenchSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.GreatBritain:
                    if (numUKSpecialActions > 0)
                    {
                        britishForcePool.ReturnSpecialAction();
                        numUKSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.USSR:
                    if (numUSSRSpecialActions > 0)
                    {
                        sovietForcePool.ReturnSpecialAction();
                        numUSSRSpecialActions--;
                    }
                    break;
                case MapInfo.CountryID.USA:
                    if (numUSSpecialActions > 0)
                    {
                        USForcePool.ReturnSpecialAction();
                        numUSSpecialActions--;
                    }
                    break;
                default:
                    throw new ArgumentException();
            }
        }

        public int GetNumSpecialActions(MapInfo.CountryID country)
        {
            if (IsNationConquered(country))
                return 0;

            switch (country)
            {
                case MapInfo.CountryID.Poland:
                    return (int)numPolishSpecialActions;
                case MapInfo.CountryID.Yugoslavia:
                    return (int)numYugoslaviaSpecialActions;
                case MapInfo.CountryID.Spain:
                    return (int)numSpanishSpecialActions;
                case MapInfo.CountryID.Turkey:
                    return (int)numTurkishSpecialActions;
                case MapInfo.CountryID.Germany:
                    return (int)numGermanSpecialActions;
                case MapInfo.CountryID.Italy:
                    return (int)numItalianSpecialActions;
                case MapInfo.CountryID.France:
                    return (int)numFrenchSpecialActions;
                case MapInfo.CountryID.GreatBritain:
                    return (int)numUKSpecialActions;
                case MapInfo.CountryID.USSR:
                    return (int)numUSSRSpecialActions;
                case MapInfo.CountryID.USA:
                    return (int)numUSSpecialActions;
                default:
                    return 0;
            }
        }

        public XmlNode SerialiseGetGameStateNode(XmlDocument xml, GameTurn.GameDate gameDateCutoffForMoveHistory)
        {
            //TODO Add Version Checking here (and at deserialize)
            #region root game state node
            XmlNode xmlGameStateNode = xml.CreateElement("EuropeEngulfedGameState");
            XmlAttribute italianMoralCollapsedAttr = xml.CreateAttribute("italianMoraleHasCollapsed");
            XmlAttribute italianHasSurrenderedAttr = xml.CreateAttribute("italianHasSurrendered");
            XmlAttribute maginotLineHasBeenBreachedAttr = xml.CreateAttribute("maginotLineHasBeenBreached");
            XmlAttribute vichyDeclaredAttr = xml.CreateAttribute("vichyDeclared");
            XmlAttribute vichyFranceOfferedAttr = xml.CreateAttribute("vichyFranceOffered");
            XmlAttribute enemyUnitsInGermanyAttr = xml.CreateAttribute("enemyUnitsInGermany");
            XmlAttribute germanUnitHasUsedItalianSeaTransportAttr = xml.CreateAttribute("germanUnitHasUsedItalianSeaTransport");
            XmlAttribute ploestiRestrictionsInEffetAttr = xml.CreateAttribute("ploestiRestrictionsInEffet");
            XmlAttribute germanyAndUSSRAtWarSinceBeginningOfTurnAttr = xml.CreateAttribute("germanyAndUSSRAtWarSinceBeginningOfTurn");
            XmlAttribute vichyFranceAtWarSinceBeginningOfTurnAttr = xml.CreateAttribute("vichyFranceAtWarSinceBeginningOfTurn");
            XmlAttribute freefrench1944UnitsAddedToUSForcePoolAttr = xml.CreateAttribute("freefrench1944UnitsAddedToUSForcePool");
            XmlAttribute stratWarfareEffectOnGermanStratMovesAttr = xml.CreateAttribute("stratWarfareEffectOnGermanStratMoves");
            XmlAttribute operationOverlordEffectOnGermanStratMovesAttr = xml.CreateAttribute("operationOverlordEffectOnGermanStratMoves");
            XmlAttribute stratWarfareEffectOnWAlliesStratMovesAttr = xml.CreateAttribute("stratWarfareEffectOnWAlliesStratMoves");
            XmlAttribute lastTurnOperationOverlordLaunchedAttr = xml.CreateAttribute("lastTurnOperationOverlordLaunched");
            XmlAttribute novgorodHasFallenAttr = xml.CreateAttribute("novgorodHasFallen");
            XmlAttribute leningradHasFallenAttr = xml.CreateAttribute("leningradHasFallen");
            XmlAttribute alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942Attr = xml.CreateAttribute("alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942");
            XmlAttribute numSovietHeavyFortificationsBuildAttr = xml.CreateAttribute("numSovietHeavyFortificationsBuild");
            XmlAttribute lastAxisMinorToReceiveFreeStepAttr = xml.CreateAttribute("lastAxisMinorToReceiveFreeStep");
            XmlAttribute westernZoneWeatherAttr = xml.CreateAttribute("westernZoneWeather");
            XmlAttribute easternZoneWeatherAttr = xml.CreateAttribute("easternZoneWeather");
            XmlAttribute southernZoneWeatherAttr = xml.CreateAttribute("southernZoneWeather");
            XmlAttribute UBoatPointsAttr = xml.CreateAttribute("UBoatPoints");
            XmlAttribute ASWLevelAttr = xml.CreateAttribute("ASWLevel");
            XmlAttribute germanFlakLevelAttr = xml.CreateAttribute("germanFlakLevel");
            XmlAttribute germanFighterPointsAttr = xml.CreateAttribute("germanFighterPoints");
            XmlAttribute germanBomberPointsAttr = xml.CreateAttribute("germanBomberPoints");
            XmlAttribute westernAlliedFlakLevelAttr = xml.CreateAttribute("westernAlliedFlakLevel");
            XmlAttribute westernAlliedFighterPointsAttr = xml.CreateAttribute("westernAlliedFighterPoints");
            XmlAttribute westernAlliedBomberPointsAttr = xml.CreateAttribute("westernAlliedBomberPoints");
            XmlAttribute V1RocketLevelAttr = xml.CreateAttribute("V1RocketLevel");
            XmlAttribute V2RocketLevelAttr = xml.CreateAttribute("V2RocketLevel");
            XmlAttribute currentGermanWERPProductionAttr = xml.CreateAttribute("currentGermanWERPProduction");
            XmlAttribute currentItalianWERPProductionAttr = xml.CreateAttribute("currentItalianWERPProduction");
            XmlAttribute currentUKWERPProductionAttr = xml.CreateAttribute("currentUKWERPProduction");
            XmlAttribute currentFrenchWERPProductionAttr = xml.CreateAttribute("currentFrenchWERPProduction");
            XmlAttribute currentUSWERPProductionAttr = xml.CreateAttribute("currentUSWERPProduction");
            XmlAttribute currentUSSRWERPProductionAttr = xml.CreateAttribute("currentUSSRWERPProduction");
            XmlAttribute russianEmergencyConscriptionTakenAttr = xml.CreateAttribute("russianEmergencyConscriptionTaken");

            italianMoralCollapsedAttr.Value = italianMoraleHasCollapsed.ToString();
            italianHasSurrenderedAttr.Value = italianHasSurrendered.ToString();
            maginotLineHasBeenBreachedAttr.Value = maginotLineHasBeenBreached.ToString();
            vichyDeclaredAttr.Value = vichyDeclared.ToString();
            vichyFranceOfferedAttr.Value = vichyFranceOffered.ToString();
            enemyUnitsInGermanyAttr.Value = enemyUnitsHaveBeenInGermany.ToString();
            germanUnitHasUsedItalianSeaTransportAttr.Value = germanUnitHasUsedItalianSeaTransport.ToString();
            ploestiRestrictionsInEffetAttr.Value = ploestiRestrictionsInEffet.ToString();
            germanyAndUSSRAtWarSinceBeginningOfTurnAttr.Value = germanyAndUSSRAtWarSinceBeginningOfTurn.ToString();
            vichyFranceAtWarSinceBeginningOfTurnAttr.Value = vichyFranceAtWarSinceBeginningOfTurn.ToString();
            freefrench1944UnitsAddedToUSForcePoolAttr.Value = freefrench1944UnitsAddedToUSForcePool.ToString();
            stratWarfareEffectOnGermanStratMovesAttr.Value = stratWarfareEffectOnGermanStratMoves.ToString();
            operationOverlordEffectOnGermanStratMovesAttr.Value = operationOverlordEffectOnGermanStratMoves.ToString();
            stratWarfareEffectOnWAlliesStratMovesAttr.Value = stratWarfareEffectOnWAlliesStratMoves.ToString();
            lastTurnOperationOverlordLaunchedAttr.Value = lastTurnOperationOverlordLaunched.ToString();
            novgorodHasFallenAttr.Value = novgorodHasFallen.ToString();
            leningradHasFallenAttr.Value = leningradHasFallen.ToString();
            alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942Attr.Value = alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942.ToString();
            numSovietHeavyFortificationsBuildAttr.Value = numSovietHeavyFortificationsBuild.ToString();
            lastAxisMinorToReceiveFreeStepAttr.Value = Enum.GetName(lastAxisMinorToReceiveFreeStep.GetType(), lastAxisMinorToReceiveFreeStep);
            westernZoneWeatherAttr.Value = currentWesternZoneWeather.ToString();
            easternZoneWeatherAttr.Value = currentEasternZoneWeather.ToString();
            southernZoneWeatherAttr.Value = currentSouthernZoneWeather.ToString();
            UBoatPointsAttr.Value = UBoatPoints.ToString();
            ASWLevelAttr.Value = ASWLevel.ToString();
            germanFlakLevelAttr.Value = germanFlakLevel.ToString();
            germanFighterPointsAttr.Value = germanFighterPoints.ToString();
            germanBomberPointsAttr.Value = germanBomberPoints.ToString();
            westernAlliedFlakLevelAttr.Value = westernAlliedFlakLevel.ToString();
            westernAlliedFighterPointsAttr.Value = westernAlliedFighterPoints.ToString();
            westernAlliedBomberPointsAttr.Value = westernAlliedBomberPoints.ToString();
            V1RocketLevelAttr.Value = V1RocketLevel.ToString();
            V2RocketLevelAttr.Value = V2RocketLevel.ToString();
            currentGermanWERPProductionAttr.Value = currentGermanWERPProduction.ToString();
            currentItalianWERPProductionAttr.Value = currentItalianWERPProduction.ToString();
            currentUKWERPProductionAttr.Value = currentUKWERPProduction.ToString();
            currentFrenchWERPProductionAttr.Value = currentFrenchWERPProduction.ToString();
            currentUSWERPProductionAttr.Value = currentUSWERPProduction.ToString();
            currentUSSRWERPProductionAttr.Value = currentUSSRWERPProduction.ToString();
            russianEmergencyConscriptionTakenAttr.Value = Enum.GetName(typeof(GameTurn.GameDate), russianEmergencyConscriptionTaken);
            xmlGameStateNode.Attributes.Append(italianMoralCollapsedAttr);
            xmlGameStateNode.Attributes.Append(italianHasSurrenderedAttr);
            xmlGameStateNode.Attributes.Append(maginotLineHasBeenBreachedAttr);
            xmlGameStateNode.Attributes.Append(vichyDeclaredAttr);
            xmlGameStateNode.Attributes.Append(vichyFranceOfferedAttr);
            xmlGameStateNode.Attributes.Append(enemyUnitsInGermanyAttr);
            xmlGameStateNode.Attributes.Append(germanUnitHasUsedItalianSeaTransportAttr);
            xmlGameStateNode.Attributes.Append(ploestiRestrictionsInEffetAttr);
            xmlGameStateNode.Attributes.Append(germanyAndUSSRAtWarSinceBeginningOfTurnAttr);
            xmlGameStateNode.Attributes.Append(vichyFranceAtWarSinceBeginningOfTurnAttr);
            xmlGameStateNode.Attributes.Append(freefrench1944UnitsAddedToUSForcePoolAttr);
            xmlGameStateNode.Attributes.Append(stratWarfareEffectOnGermanStratMovesAttr);
            xmlGameStateNode.Attributes.Append(operationOverlordEffectOnGermanStratMovesAttr);
            xmlGameStateNode.Attributes.Append(stratWarfareEffectOnWAlliesStratMovesAttr);
            xmlGameStateNode.Attributes.Append(lastTurnOperationOverlordLaunchedAttr);
            xmlGameStateNode.Attributes.Append(leningradHasFallenAttr);
            xmlGameStateNode.Attributes.Append(novgorodHasFallenAttr);
            xmlGameStateNode.Attributes.Append(alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942Attr);
            xmlGameStateNode.Attributes.Append(numSovietHeavyFortificationsBuildAttr);
            xmlGameStateNode.Attributes.Append(lastAxisMinorToReceiveFreeStepAttr);
            xmlGameStateNode.Attributes.Append(westernZoneWeatherAttr);
            xmlGameStateNode.Attributes.Append(easternZoneWeatherAttr);
            xmlGameStateNode.Attributes.Append(southernZoneWeatherAttr);
            xmlGameStateNode.Attributes.Append(UBoatPointsAttr);
            xmlGameStateNode.Attributes.Append(ASWLevelAttr);
            xmlGameStateNode.Attributes.Append(germanFlakLevelAttr);
            xmlGameStateNode.Attributes.Append(germanFighterPointsAttr);
            xmlGameStateNode.Attributes.Append(germanBomberPointsAttr);
            xmlGameStateNode.Attributes.Append(westernAlliedFlakLevelAttr);
            xmlGameStateNode.Attributes.Append(westernAlliedFighterPointsAttr);
            xmlGameStateNode.Attributes.Append(westernAlliedBomberPointsAttr);
            xmlGameStateNode.Attributes.Append(V1RocketLevelAttr);
            xmlGameStateNode.Attributes.Append(V2RocketLevelAttr);
            xmlGameStateNode.Attributes.Append(currentGermanWERPProductionAttr);
            xmlGameStateNode.Attributes.Append(currentItalianWERPProductionAttr);
            xmlGameStateNode.Attributes.Append(currentUKWERPProductionAttr);
            xmlGameStateNode.Attributes.Append(currentFrenchWERPProductionAttr);
            xmlGameStateNode.Attributes.Append(currentUSWERPProductionAttr);
            xmlGameStateNode.Attributes.Append(currentUSSRWERPProductionAttr);
            xmlGameStateNode.Attributes.Append(russianEmergencyConscriptionTakenAttr);
            #endregion

            XmlNode nextDateAllowed = xml.CreateElement("nextBritishFleetAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextBritishFleetAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            nextDateAllowed = xml.CreateElement("nextFrenchFleetAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextFrenchFleetAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            nextDateAllowed = xml.CreateElement("nextItalianFleetAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextItalianFleetAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            nextDateAllowed = xml.CreateElement("nextRussianFleetAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextRussianFleetAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            nextDateAllowed = xml.CreateElement("nextGermanFleetAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextGermanFleetAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            nextDateAllowed = xml.CreateElement("nextUSFleetAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextUSFleetAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            nextDateAllowed = xml.CreateElement("nextASWAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextASWAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            nextDateAllowed = xml.CreateElement("nextBritishFlakAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextBritishFlakAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            nextDateAllowed = xml.CreateElement("nextGermanFlakAllowed");
            nextDateAllowed.InnerText = Enum.GetName(typeof(GameTurn.GameDate), nextGermanFlakAllowed);
            xmlGameStateNode.AppendChild(nextDateAllowed);
            xmlGameStateNode.AppendChild(currentGameTurn.Serialise(xml));
            XmlNode countriesAtWarNode = xml.CreateElement("CountriesAtWar");
            foreach (MapInfo.CountryID country in countriesAtWar.Keys)
            {
                if (countriesAtWar[country])
                {
                    XmlNode countryNode = xml.CreateElement("CountryAtWar");
                    countryNode.InnerText = Enum.GetName(typeof(MapInfo.CountryID), country);
                    countriesAtWarNode.AppendChild(countryNode);
                }
            }
            xmlGameStateNode.AppendChild(countriesAtWarNode);

            XmlNode countriesConqueredNode = xml.CreateElement("CountriesConquered");
            foreach (MapInfo.CountryID country in countriesConquered.Keys)
            {
                if (countriesConquered[country])
                {
                    XmlNode countryNode = xml.CreateElement("CountryConquered");
                    countryNode.InnerText = Enum.GetName(typeof(MapInfo.CountryID), country);
                    countriesConqueredNode.AppendChild(countryNode);
                }
            }
            xmlGameStateNode.AppendChild(countriesConqueredNode);

            XmlNode countriesJoinedAlliesNode = xml.CreateElement("CountriesJoinedAllies");
            foreach (MapInfo.CountryID country in countriesJoinedAllies.Keys)
            {
                XmlNode countryNode = xml.CreateElement(Enum.GetName(typeof(MapInfo.CountryID), country));
                countryNode.InnerText = countriesJoinedAllies[country].ToString();
                countriesJoinedAlliesNode.AppendChild(countryNode);
            }
            xmlGameStateNode.AppendChild(countriesJoinedAlliesNode);

            XmlNode specialActions = xml.CreateElement("PolishSpecialActions");
            specialActions.InnerText = numPolishSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("TurkishSpecialActions");
            specialActions.InnerText = numTurkishSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("SpanishSpecialActions");
            specialActions.InnerText = numSpanishSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("YugoslaviaSpecialActions");
            specialActions.InnerText = numYugoslaviaSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("GermanSpecialActions");
            specialActions.InnerText = numGermanSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("ItalianSpecialActions");
            specialActions.InnerText = numItalianSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("FrenchSpecialActions");
            specialActions.InnerText = numFrenchSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("UKSpecialActions");
            specialActions.InnerText = numUKSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("USSRSpecialActions");
            specialActions.InnerText = numUSSRSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);
            specialActions = xml.CreateElement("USSpecialActions");
            specialActions.InnerText = numUSSpecialActions.ToString();
            xmlGameStateNode.AppendChild(specialActions);

            XmlNode stratMoves = xml.CreateElement("numFrenchStratMoves");
            stratMoves.InnerText = numFrenchStratMoves.ToString();
            xmlGameStateNode.AppendChild(stratMoves);
            stratMoves = xml.CreateElement("numBritishStratMoves");
            stratMoves.InnerText = numBritishStratMoves.ToString();
            xmlGameStateNode.AppendChild(stratMoves);
            stratMoves = xml.CreateElement("numUSStratMoves");
            stratMoves.InnerText = numUSStratMoves.ToString();
            xmlGameStateNode.AppendChild(stratMoves);
            stratMoves = xml.CreateElement("numUSSRStratMoves");
            stratMoves.InnerText = numUSSRStratMoves.ToString();
            xmlGameStateNode.AppendChild(stratMoves);
            stratMoves = xml.CreateElement("numGermanStratMoves");
            stratMoves.InnerText = numGermanStratMoves.ToString();
            xmlGameStateNode.AppendChild(stratMoves);
            stratMoves = xml.CreateElement("numItalianStratMoves");
            stratMoves.InnerText = numItalianStratMoves.ToString();
            xmlGameStateNode.AppendChild(stratMoves);

            XmlNode forcePoolNode = xml.CreateElement("GermanForcePool");
            forcePoolNode.AppendChild(germanForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("FrenchForcePool");
            forcePoolNode.AppendChild(frenchForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("BritishForcePool");
            forcePoolNode.AppendChild(britishForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("BulgariaForcePool");
            forcePoolNode.AppendChild(bulgariaForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("FinlandForcePool");
            forcePoolNode.AppendChild(finlandForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("HungaryForcePool");
            forcePoolNode.AppendChild(hungaryForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("RumaniaForcePool");
            forcePoolNode.AppendChild(rumaniaForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("ItalianForcePool");
            forcePoolNode.AppendChild(italianForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("SovietForcePool");
            forcePoolNode.AppendChild(sovietForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("USForcePool");
            forcePoolNode.AppendChild(USForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("BelgiumForcePool");
            forcePoolNode.AppendChild(belgiumForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("DenmarkForcePool");
            forcePoolNode.AppendChild(denmarkForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("GreeceForcePool");
            forcePoolNode.AppendChild(greeceForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("TheNetherLandsForcePool");
            forcePoolNode.AppendChild(theNetherLandsForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("NorwayForcePool");
            forcePoolNode.AppendChild(norwayForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("PolandForcePool");
            forcePoolNode.AppendChild(polandForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("PortugalForcePool");
            forcePoolNode.AppendChild(portugalForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("SpainForcePool");
            forcePoolNode.AppendChild(spainForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("SwedenForcePool");
            forcePoolNode.AppendChild(swedenForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("SwitzerlandForcePool");
            forcePoolNode.AppendChild(switzerlandForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("TurkeyForcePool");
            forcePoolNode.AppendChild(turkeyForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);
            forcePoolNode = xml.CreateElement("YugolaviaForcePool");
            forcePoolNode.AppendChild(yugolaviaForcePool.Serialise(xml));
            xmlGameStateNode.AppendChild(forcePoolNode);

            System.Xml.XmlNode regionStatesNode = xml.CreateElement("RegionStates");
            foreach (RegionState regionState in regions)
            {
                regionStatesNode.AppendChild(regionState.Serialise(xml));
            }
            xmlGameStateNode.AppendChild(regionStatesNode);

            XmlNode listOfMovesNode = xml.CreateElement("ListOfMoves");
            foreach (GameTurn.GameDate gameDate in listOfMoves.Keys)
            {
                if (gameDate >= gameDateCutoffForMoveHistory)
                {
                    foreach (GameTurn.GamePhase gamePhase in listOfMoves[gameDate].Keys)
                    {
                        foreach (GameTurn.GameSubPhase gameSubPhase in listOfMoves[gameDate][gamePhase].Keys)
                        {
                            foreach (Move move in listOfMoves[gameDate][gamePhase][gameSubPhase])
                            {
                                listOfMovesNode.AppendChild(move.Serialise(xml));
                            }
                        }
                    }
                }
            }
            xmlGameStateNode.AppendChild(listOfMovesNode);

            return xmlGameStateNode;
        }

        public XmlDocument Serialise(GameTurn.GameDate gameDateCutoffForMoveHistory)
        {
            XmlDocument xml = new XmlDocument();
            xml.AppendChild(SerialiseGetGameStateNode(xml, gameDateCutoffForMoveHistory));
            return xml;
        }

        public XmlDocument Serialise()
        {
            return Serialise(GameTurn.GameDate.SepOct39);
        }

        public void MergeGameStateMoves(GameState gameStateToMerge)
        {
            GameTurn.GameDate earliestGameDate = GameTurn.GameDate.NovDec45;
            foreach (GameTurn.GameDate gameDate in listOfMoves.Keys)
            {
                if (gameDate < earliestGameDate)
                    earliestGameDate = gameDate;
            }

            foreach(GameTurn.GameDate gameDate in gameStateToMerge.listOfMoves.Keys)
            {
                if (gameDate < earliestGameDate)
                    this.listOfMoves.Add(gameDate, gameStateToMerge.listOfMoves[gameDate]);
            }
        }

        public static GameState Deserialise(System.Xml.XmlDocument xml)
        {
            return Deserialise(xml.DocumentElement);
        }

        public static GameState Deserialise(System.Xml.XmlNode gameStateNode)
        {
            GameState gameStateToReturn = new GameState();
            gameStateToReturn.italianMoraleHasCollapsed = bool.Parse(gameStateNode.Attributes["italianMoraleHasCollapsed"].Value);
            gameStateToReturn.italianHasSurrendered = bool.Parse(gameStateNode.Attributes["italianHasSurrendered"].Value);
            gameStateToReturn.maginotLineHasBeenBreached = bool.Parse(gameStateNode.Attributes["maginotLineHasBeenBreached"].Value);
            gameStateToReturn.vichyDeclared = bool.Parse(gameStateNode.Attributes["vichyDeclared"].Value);
            gameStateToReturn.vichyFranceOffered = bool.Parse(gameStateNode.Attributes["vichyFranceOffered"].Value);
            gameStateToReturn.enemyUnitsHaveBeenInGermany = bool.Parse(gameStateNode.Attributes["enemyUnitsInGermany"].Value);
            gameStateToReturn.germanUnitHasUsedItalianSeaTransport = bool.Parse(gameStateNode.Attributes["germanUnitHasUsedItalianSeaTransport"].Value);
            try
            {
                gameStateToReturn.ploestiRestrictionsInEffet = bool.Parse(gameStateNode.Attributes["ploestiRestrictionsInEffet"].Value);
            }
            catch
            {
                //because this is a new setting and we want to be able to load old games
                gameStateToReturn.ploestiRestrictionsInEffet = false;
            }
            
            gameStateToReturn.germanyAndUSSRAtWarSinceBeginningOfTurn = bool.Parse(gameStateNode.Attributes["germanyAndUSSRAtWarSinceBeginningOfTurn"].Value);
            gameStateToReturn.vichyFranceAtWarSinceBeginningOfTurn = bool.Parse(gameStateNode.Attributes["vichyFranceAtWarSinceBeginningOfTurn"].Value);
            gameStateToReturn.freefrench1944UnitsAddedToUSForcePool = bool.Parse(gameStateNode.Attributes["freefrench1944UnitsAddedToUSForcePool"].Value);
            gameStateToReturn.stratWarfareEffectOnGermanStratMoves = int.Parse(gameStateNode.Attributes["stratWarfareEffectOnGermanStratMoves"].Value);
            gameStateToReturn.operationOverlordEffectOnGermanStratMoves = int.Parse(gameStateNode.Attributes["operationOverlordEffectOnGermanStratMoves"].Value);
            gameStateToReturn.stratWarfareEffectOnWAlliesStratMoves = int.Parse(gameStateNode.Attributes["stratWarfareEffectOnWAlliesStratMoves"].Value);
            gameStateToReturn.lastTurnOperationOverlordLaunched = bool.Parse(gameStateNode.Attributes["lastTurnOperationOverlordLaunched"].Value);
            gameStateToReturn.leningradHasFallen = bool.Parse(gameStateNode.Attributes["leningradHasFallen"].Value);
            gameStateToReturn.novgorodHasFallen = bool.Parse(gameStateNode.Attributes["novgorodHasFallen"].Value);
            gameStateToReturn.alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942 = bool.Parse(gameStateNode.Attributes["alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942"].Value);
            gameStateToReturn.numSovietHeavyFortificationsBuild = int.Parse(gameStateNode.Attributes["numSovietHeavyFortificationsBuild"].Value);
            gameStateToReturn.lastAxisMinorToReceiveFreeStep = (MapInfo.CountryID)Enum.Parse(typeof(MapInfo.CountryID), gameStateNode.Attributes["lastAxisMinorToReceiveFreeStep"].Value);
            gameStateToReturn.currentWesternZoneWeather = (Weather)Enum.Parse(typeof(Weather),gameStateNode.Attributes["westernZoneWeather"].Value);
            gameStateToReturn.currentEasternZoneWeather = (Weather)Enum.Parse(typeof(Weather),gameStateNode.Attributes["easternZoneWeather"].Value);
            gameStateToReturn.currentSouthernZoneWeather = (Weather)Enum.Parse(typeof(Weather),gameStateNode.Attributes["southernZoneWeather"].Value);
            gameStateToReturn.UBoatPoints = (uint)Int32.Parse(gameStateNode.Attributes["UBoatPoints"].Value);
            gameStateToReturn.ASWLevel = (uint)Int32.Parse(gameStateNode.Attributes["ASWLevel"].Value);
            gameStateToReturn.germanFlakLevel = (uint)Int32.Parse(gameStateNode.Attributes["germanFlakLevel"].Value);
            gameStateToReturn.germanFighterPoints = (uint)Int32.Parse(gameStateNode.Attributes["germanFighterPoints"].Value);
            gameStateToReturn.germanBomberPoints = (uint)Int32.Parse(gameStateNode.Attributes["germanBomberPoints"].Value);
            gameStateToReturn.westernAlliedFlakLevel = (uint)Int32.Parse(gameStateNode.Attributes["westernAlliedFlakLevel"].Value);
            gameStateToReturn.westernAlliedFighterPoints = (uint)Int32.Parse(gameStateNode.Attributes["westernAlliedFighterPoints"].Value);
            gameStateToReturn.westernAlliedBomberPoints = (uint)Int32.Parse(gameStateNode.Attributes["westernAlliedBomberPoints"].Value);
            gameStateToReturn.V1RocketLevel = (uint)Int32.Parse(gameStateNode.Attributes["V1RocketLevel"].Value);
            gameStateToReturn.V2RocketLevel = (uint)Int32.Parse(gameStateNode.Attributes["V2RocketLevel"].Value);
            gameStateToReturn.currentGermanWERPProduction = Int32.Parse(gameStateNode.Attributes["currentGermanWERPProduction"].Value);
            gameStateToReturn.currentItalianWERPProduction = Int32.Parse(gameStateNode.Attributes["currentItalianWERPProduction"].Value);
            gameStateToReturn.currentUKWERPProduction = Int32.Parse(gameStateNode.Attributes["currentUKWERPProduction"].Value);
            gameStateToReturn.currentFrenchWERPProduction = Int32.Parse(gameStateNode.Attributes["currentFrenchWERPProduction"].Value);
            gameStateToReturn.currentUSWERPProduction = Int32.Parse(gameStateNode.Attributes["currentUSWERPProduction"].Value);
            gameStateToReturn.currentUSSRWERPProduction = Int32.Parse(gameStateNode.Attributes["currentUSSRWERPProduction"].Value);
            gameStateToReturn.russianEmergencyConscriptionTaken = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), gameStateNode.Attributes["russianEmergencyConscriptionTaken"].Value);
            foreach(XmlNode node in gameStateNode)
            {
                switch(node.Name)
                {
                    case "nextBritishFleetAllowed":
                        gameStateToReturn.nextBritishFleetAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "nextFrenchFleetAllowed":
                        gameStateToReturn.nextFrenchFleetAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "nextItalianFleetAllowed":
                        gameStateToReturn.nextItalianFleetAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "nextRussianFleetAllowed":
                        gameStateToReturn.nextRussianFleetAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "nextGermanFleetAllowed":
                        gameStateToReturn.nextGermanFleetAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "nextUSFleetAllowed":
                        gameStateToReturn.nextUSFleetAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "nextASWAllowed":
                        gameStateToReturn.nextASWAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "nextBritishFlakAllowed":
                        gameStateToReturn.nextBritishFlakAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "nextGermanFlakAllowed":
                        gameStateToReturn.nextGermanFlakAllowed = (GameTurn.GameDate)Enum.Parse(typeof(GameTurn.GameDate), node.InnerText);
                        break;
                    case "PolishSpecialActions":
                        gameStateToReturn.numPolishSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "TurkishSpecialActions":
                        gameStateToReturn.numTurkishSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "SpanishSpecialActions":
                        gameStateToReturn.numSpanishSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "YugoslaviaSpecialActions":
                        gameStateToReturn.numYugoslaviaSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "GermanSpecialActions":
                        gameStateToReturn.numGermanSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "ItalianSpecialActions":
                        gameStateToReturn.numItalianSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "FrenchSpecialActions":
                        gameStateToReturn.numFrenchSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "UKSpecialActions":
                        gameStateToReturn.numUKSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "USSRSpecialActions":
                        gameStateToReturn.numUSSRSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "USSpecialActions":
                        gameStateToReturn.numUSSpecialActions = (uint)Int32.Parse(node.InnerText);
                        break;
                    case "numFrenchStratMoves":
                        gameStateToReturn.numFrenchStratMoves = (int)Int32.Parse(node.InnerText);
                        break;
                    case "numUSSRStratMoves":
                        gameStateToReturn.numUSSRStratMoves = (int)Int32.Parse(node.InnerText);
                        break;
                    case "numBritishStratMoves":
                        gameStateToReturn.numBritishStratMoves = (int)Int32.Parse(node.InnerText);
                        break;
                    case "numUSStratMoves":
                        gameStateToReturn.numUSStratMoves = (int)Int32.Parse(node.InnerText);
                        break;
                    case "numGermanStratMoves":
                        gameStateToReturn.numGermanStratMoves = (int)Int32.Parse(node.InnerText);
                        break;
                    case "numItalianStratMoves":
                        gameStateToReturn.numItalianStratMoves = (int)Int32.Parse(node.InnerText);
                        break;
                    case "CountriesAtWar":
                        foreach(XmlNode countryAtWarNode in node)
                        {
                            if(countryAtWarNode.Name == "CountryAtWar")
                            {
                                gameStateToReturn.countriesAtWar[(MapInfo.CountryID)Enum.Parse(typeof(MapInfo.CountryID), countryAtWarNode.InnerText)] = true;
                            }
                        }
                        break;
                    case "CountriesConquered":
                        foreach (XmlNode countryConqueredNode in node)
                        {
                            if (countryConqueredNode.Name == "CountryConquered")
                            {
                                gameStateToReturn.countriesConquered[(MapInfo.CountryID)Enum.Parse(typeof(MapInfo.CountryID), countryConqueredNode.InnerText)] = true;
                            }
                        }
                        break;
                    case "CountriesJoinedAllies":
                        foreach (XmlNode countryJoinedAlliesNode in node)
                        {
                            gameStateToReturn.countriesJoinedAllies[(MapInfo.CountryID)Enum.Parse(typeof(MapInfo.CountryID), countryJoinedAlliesNode.Name)] = bool.Parse(countryJoinedAlliesNode.InnerText);
                        }
                        break;
                    case "GameTurn":
                        gameStateToReturn.currentGameTurn = GameTurn.Deserialise(node);
                        break;
                    case "GermanForcePool":
                        gameStateToReturn.germanForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "FrenchForcePool":
                        gameStateToReturn.frenchForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "BritishForcePool":
                        gameStateToReturn.britishForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "BulgariaForcePool":
                        gameStateToReturn.bulgariaForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "FinlandForcePool":
                        gameStateToReturn.finlandForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "HungaryForcePool":
                        gameStateToReturn.hungaryForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "RumaniaForcePool":
                        gameStateToReturn.rumaniaForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "ItalianForcePool":
                        gameStateToReturn.italianForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "SovietForcePool":
                        gameStateToReturn.sovietForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "USForcePool":
                        gameStateToReturn.USForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "BelgiumForcePool":
                        gameStateToReturn.belgiumForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "DenmarkForcePool":
                        gameStateToReturn.denmarkForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "GreeceForcePool":
                        gameStateToReturn.greeceForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "TheNetherLandsForcePool":
                        gameStateToReturn.theNetherLandsForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "NorwayForcePool":
                        gameStateToReturn.norwayForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "PolandForcePool":
                        gameStateToReturn.polandForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "PortugalForcePool":
                        gameStateToReturn.portugalForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "SpainForcePool":
                        gameStateToReturn.spainForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "SwedenForcePool":
                        gameStateToReturn.swedenForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "SwitzerlandForcePool":
                        gameStateToReturn.switzerlandForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "TurkeyForcePool":
                        gameStateToReturn.turkeyForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "YugolaviaForcePool":
                        gameStateToReturn.yugolaviaForcePool = ForcePool.Deserialise(node.ChildNodes[0]);
                        break;
                    case "RegionStates":
                        foreach(XmlNode regionStateNode in node)
                        {
                            RegionState regionStateToRemove = gameStateToReturn.GetRegionState((MapInfo.RegionID)Enum.Parse(typeof(MapInfo.RegionID), regionStateNode.Attributes["RegionID"].Value));
                            gameStateToReturn.regions.Remove(regionStateToRemove);
                            gameStateToReturn.regions.Add(RegionState.Deserialise(regionStateNode));
                        }
                        break;
                    case "ListOfMoves":
                        foreach (XmlNode moveNode in node)
                        {
                            Move move = Move.Deserialise(moveNode);
                            gameStateToReturn.AddMoveToListOfMoves(move);
                        }
                        break;
                }
            }

            return gameStateToReturn;
        }

        public bool Equals(GameState gameStateToCompare)
        {
            if (this.italianMoraleHasCollapsed != gameStateToCompare.italianMoraleHasCollapsed)
                return false;
            if (this.italianHasSurrendered != gameStateToCompare.italianHasSurrendered)
                return false;
            if (this.maginotLineHasBeenBreached != gameStateToCompare.maginotLineHasBeenBreached)
                return false;
            if (this.vichyDeclared != gameStateToCompare.vichyDeclared)
                return false;
            if (this.vichyFranceOffered != gameStateToCompare.vichyFranceOffered)
                return false;
            if (this.enemyUnitsHaveBeenInGermany != gameStateToCompare.enemyUnitsHaveBeenInGermany)
                return false;
            if (this.germanUnitHasUsedItalianSeaTransport != gameStateToCompare.germanUnitHasUsedItalianSeaTransport)
                return false;
            if (this.ploestiRestrictionsInEffet != gameStateToCompare.ploestiRestrictionsInEffet)
                return false;
            if (this.germanyAndUSSRAtWarSinceBeginningOfTurn != gameStateToCompare.germanyAndUSSRAtWarSinceBeginningOfTurn)
                return false;
            if (this.vichyFranceAtWarSinceBeginningOfTurn != gameStateToCompare.vichyFranceAtWarSinceBeginningOfTurn)
                return false;
            if (this.stratWarfareEffectOnGermanStratMoves != gameStateToCompare.stratWarfareEffectOnGermanStratMoves)
                return false;
            if (this.operationOverlordEffectOnGermanStratMoves != gameStateToCompare.operationOverlordEffectOnGermanStratMoves)
                return false;
            if (this.stratWarfareEffectOnWAlliesStratMoves != gameStateToCompare.stratWarfareEffectOnWAlliesStratMoves)
                return false;
            if (this.lastTurnOperationOverlordLaunched != gameStateToCompare.lastTurnOperationOverlordLaunched)
                return false;
            if (this.novgorodHasFallen != gameStateToCompare.novgorodHasFallen)
                return false;
            if (this.leningradHasFallen != gameStateToCompare.leningradHasFallen)
                return false;
            if (this.alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942 != gameStateToCompare.alliesSuccessfulControlOfFranceRegionOrBeachHeadAfter1942)
                return false;
            if (this.numSovietHeavyFortificationsBuild != gameStateToCompare.numSovietHeavyFortificationsBuild)
                return false;
            if (this.lastAxisMinorToReceiveFreeStep != gameStateToCompare.lastAxisMinorToReceiveFreeStep)
                return false;
            if (this.currentWesternZoneWeather != gameStateToCompare.currentWesternZoneWeather)
                return false;
            if (this.currentEasternZoneWeather != gameStateToCompare.currentEasternZoneWeather)
                return false;
            if (this.currentSouthernZoneWeather != gameStateToCompare.currentSouthernZoneWeather)
                return false;
            if(this.numPolishSpecialActions != gameStateToCompare.numPolishSpecialActions)
                return false;
            if(this.numTurkishSpecialActions != gameStateToCompare.numTurkishSpecialActions)
                return false;
            if(this.numSpanishSpecialActions != gameStateToCompare.numSpanishSpecialActions)
                return false;
            if(this.numYugoslaviaSpecialActions != gameStateToCompare.numYugoslaviaSpecialActions)
                return false;
            if(this.numGermanSpecialActions != gameStateToCompare.numGermanSpecialActions)
                return false;
            if(this.numItalianSpecialActions != gameStateToCompare.numItalianSpecialActions)
                return false;
            if(this.numFrenchSpecialActions != gameStateToCompare.numFrenchSpecialActions)
                return false;
            if(this.numUKSpecialActions != gameStateToCompare.numUKSpecialActions)
                return false;
            if(this.numUSSRSpecialActions != gameStateToCompare.numUSSRSpecialActions)
                return false;
            if(this.numUSSpecialActions != gameStateToCompare.numUSSpecialActions)
                return false;
            if(this.nextBritishFleetAllowed != gameStateToCompare.nextBritishFleetAllowed)
                return false;
            if(this.nextFrenchFleetAllowed != gameStateToCompare.nextFrenchFleetAllowed)
                return false;
            if(this.nextItalianFleetAllowed != gameStateToCompare.nextItalianFleetAllowed)
                return false;
            if(this.nextRussianFleetAllowed != gameStateToCompare.nextRussianFleetAllowed)
                return false;
            if(this.nextGermanFleetAllowed != gameStateToCompare.nextGermanFleetAllowed)
                return false;
            if(this.nextUSFleetAllowed != gameStateToCompare.nextUSFleetAllowed)
                return false;
            if(this.nextASWAllowed != gameStateToCompare.nextASWAllowed)
                return false;
            if(this.nextBritishFlakAllowed != gameStateToCompare.nextBritishFlakAllowed)
                return false;
            if(this.nextGermanFlakAllowed != gameStateToCompare.nextGermanFlakAllowed)
                return false;
            if(!this.currentGameTurn.Equals(gameStateToCompare.currentGameTurn))
                 return false;
            if(this.UBoatPoints != gameStateToCompare.UBoatPoints)
                return false;
            if(this.ASWLevel != gameStateToCompare.ASWLevel)
                return false;
            if(this.germanFlakLevel != gameStateToCompare.germanFlakLevel)
                return false;
            if(this.germanFighterPoints != gameStateToCompare.germanFighterPoints)
                return false;
            if(this.germanBomberPoints != gameStateToCompare.germanBomberPoints)
                return false;
            if(this.westernAlliedFlakLevel != gameStateToCompare.westernAlliedFlakLevel)
                return false;
            if(this.westernAlliedFighterPoints != gameStateToCompare.westernAlliedFighterPoints)
                return false;
            if(this.westernAlliedBomberPoints != gameStateToCompare.westernAlliedBomberPoints)
                return false;
            if(this.V1RocketLevel != gameStateToCompare.V1RocketLevel)
                return false;
            if(this.V2RocketLevel != gameStateToCompare.V2RocketLevel)
                return false;
            if(this.currentGermanWERPProduction != gameStateToCompare.currentGermanWERPProduction)
                return false;
            if(this.currentItalianWERPProduction != gameStateToCompare.currentItalianWERPProduction)
                return false;
            if(this.currentUKWERPProduction != gameStateToCompare.currentUKWERPProduction)
                return false;
            if (this.currentFrenchWERPProduction != gameStateToCompare.currentFrenchWERPProduction)
                return false;
            if(this.currentUSWERPProduction != gameStateToCompare.currentUSSRWERPProduction)
                return false;
            if (this.currentUSWERPProduction != gameStateToCompare.currentUSSRWERPProduction)
                return false;
            if (this.russianEmergencyConscriptionTaken != gameStateToCompare.russianEmergencyConscriptionTaken)
                return false;

            foreach(MapInfo.CountryID country in this.countriesAtWar.Keys)
            {
                if(gameStateToCompare.countriesAtWar.ContainsKey(country))
                {
                    if(countriesAtWar[country] != gameStateToCompare.countriesAtWar[country])
                        return false;
                }
                else
                    return false;
            }

            foreach (MapInfo.CountryID country in this.countriesConquered.Keys)
            {
                if (gameStateToCompare.countriesConquered.ContainsKey(country))
                {
                    if (countriesConquered[country] != gameStateToCompare.countriesConquered[country])
                        return false;
                }
                else
                    return false;
            }

            foreach (MapInfo.CountryID country in this.countriesJoinedAllies.Keys)
            {
                if (gameStateToCompare.countriesJoinedAllies.ContainsKey(country))
                {
                    if (countriesJoinedAllies[country] != gameStateToCompare.countriesJoinedAllies[country])
                        return false;
                }
                else
                    return false;
            }

            if(!this.germanForcePool.Equals(gameStateToCompare.germanForcePool))
                return false;
            if(!this.frenchForcePool.Equals(gameStateToCompare.frenchForcePool))
                return false;
            if(!this.britishForcePool.Equals(gameStateToCompare.britishForcePool))
                return false;
            if(!this.bulgariaForcePool.Equals(gameStateToCompare.bulgariaForcePool))
                return false;
            if(!this.finlandForcePool.Equals(gameStateToCompare.finlandForcePool))
                return false;
            if(!this.hungaryForcePool.Equals(gameStateToCompare.hungaryForcePool))
                return false;
            if(!this.rumaniaForcePool.Equals(gameStateToCompare.rumaniaForcePool))
                return false;
            if(!this.italianForcePool.Equals(gameStateToCompare.italianForcePool))
                return false;
            if(!this.sovietForcePool.Equals(gameStateToCompare.sovietForcePool))
                return false;
            if(!this.USForcePool.Equals(gameStateToCompare.USForcePool))
                return false;
            if(!this.belgiumForcePool.Equals(gameStateToCompare.belgiumForcePool))
                return false;
            if(!this.denmarkForcePool.Equals(gameStateToCompare.denmarkForcePool))
                return false;
            if(!this.greeceForcePool.Equals(gameStateToCompare.greeceForcePool))
                return false;
            if(!this.theNetherLandsForcePool.Equals(gameStateToCompare.theNetherLandsForcePool))
                return false;
            if(!this.norwayForcePool.Equals(gameStateToCompare.norwayForcePool))
                return false;
            if(!this.polandForcePool.Equals(gameStateToCompare.polandForcePool))
                return false;
            if(!this.portugalForcePool.Equals(gameStateToCompare.portugalForcePool))
                return false;
            if(!this.spainForcePool.Equals(gameStateToCompare.spainForcePool))
                return false;
            if(!this.swedenForcePool.Equals(gameStateToCompare.swedenForcePool))
                return false;
            if(!this.switzerlandForcePool.Equals(gameStateToCompare.switzerlandForcePool))
                return false;
            if(!this.turkeyForcePool.Equals(gameStateToCompare.turkeyForcePool))
                return false;
            if(!this.yugolaviaForcePool.Equals(gameStateToCompare.yugolaviaForcePool))
                return false;
            if(!this.spainForcePool.Equals(gameStateToCompare.spainForcePool))
                return false;
            List<RegionState> regionStatesToCompare = new List<RegionState>(gameStateToCompare.regions);
            if (this.regions.Count != regionStatesToCompare.Count)
                return false;
            foreach (RegionState regionState in this.regions)
            {
                bool found = false;
                foreach(RegionState regionStateToCompare in regionStatesToCompare)
                {
                    if(regionStateToCompare.Equals(regionState))
                    {
                        found = true;
                        regionStatesToCompare.Remove(regionStateToCompare);
                        break;
                    }
                }
                if (!found)
                    return false;
            }

            return true;
        }

        public static List<ForcePoolAdjustment> GetListOfForcePoolAdjustments(GameController.playerType player, GameTurn.GameDate gameDate)
        {
            List<ForcePoolAdjustment> listToReturn = new List<ForcePoolAdjustment>();
            foreach(ForcePoolAdjustment forcePoolAdjustment in forcePoolAdjustments)
            {
                if(forcePoolAdjustment.gameDate == gameDate)
                {
                    if(player == GameController.playerType.AxisPlayer)
                    {
                        if (forcePoolAdjustment.country == MapInfo.CountryID.Germany)
                            listToReturn.Add(forcePoolAdjustment);
                    }
                    else
                    {
                        if (forcePoolAdjustment.country != MapInfo.CountryID.Germany)
                            listToReturn.Add(forcePoolAdjustment);
                    }
                }
            }

            return listToReturn;
        }

        public static void GetListOfPlayingPiecesToDeploy(List<PlayingPiece> listOfPlayingPieces, MapInfo.CountryID countryToDeploy)
        {
            switch(countryToDeploy)
            {
                case MapInfo.CountryID.VichyFrance:
                    listOfPlayingPieces.AddRange(vichyFranceSetup);
                    break;
                case MapInfo.CountryID.Belgium:
                    listOfPlayingPieces.AddRange(belgiumSetup);
                    break;
                case MapInfo.CountryID.Denmark:
                    listOfPlayingPieces.AddRange(denmarkSetup);
                    break;
                case MapInfo.CountryID.Greece:
                    listOfPlayingPieces.AddRange(greeceSetup);
                    break;
                case MapInfo.CountryID.Netherlands:
                    listOfPlayingPieces.AddRange(netherlandsSetup);
                    break;
                case MapInfo.CountryID.Norway:
                    listOfPlayingPieces.AddRange(norwaySetup);
                    break;
                case MapInfo.CountryID.Portugal:
                    listOfPlayingPieces.AddRange(portugalSetup);
                    break;
                case MapInfo.CountryID.Spain:
                    listOfPlayingPieces.AddRange(spainSetup);
                    break;
                case MapInfo.CountryID.Sweden:
                    listOfPlayingPieces.AddRange(swedenSetup);
                    break;
                case MapInfo.CountryID.Switzerland:
                    listOfPlayingPieces.AddRange(switzerlandSetup);
                    break;
                case MapInfo.CountryID.Turkey:
                    listOfPlayingPieces.AddRange(turkeySetup);
                    break;
                case MapInfo.CountryID.Yugoslavia:
                    listOfPlayingPieces.AddRange(yugoslaviaSetup);
                    break;
                case MapInfo.CountryID.Bulgaria:
                    listOfPlayingPieces.AddRange(bulgariaSetup);
                    break;
                case MapInfo.CountryID.Finland:
                    listOfPlayingPieces.AddRange(finlandSetup);
                    break;
                case MapInfo.CountryID.Hungary:
                    listOfPlayingPieces.AddRange(hungarySetup);
                    break;
                case MapInfo.CountryID.Rumania:
                    listOfPlayingPieces.AddRange(rumaniaSetup);
                    break;
                default:
                    throw new NotImplementedException();
            }
        }

        public int beachHeadAvailable(MapInfo.CountryID country)
        {
            return GetForcePoolForCountry(country).CurrentBeachHeads;
        }

        public bool DeployBeachhead(MapInfo.RegionID regionToDeployTo, MapInfo.CountryID countryDoingAmphibiousAssault)
        {
            LandRegionState regionStateToPlaceBeachHead = (LandRegionState)GetRegionState(regionToDeployTo);
            if (countryDoingAmphibiousAssault == MapInfo.CountryID.France)
            {
                if (!GetForcePoolForCountry(MapInfo.CountryID.France).GetBeachhead())
                    return false;
                regionStateToPlaceBeachHead.BeachHead = true;
                regionStateToPlaceBeachHead.BeachHeadCountry = MapInfo.CountryID.France;
            }
            else if(countryDoingAmphibiousAssault == MapInfo.CountryID.Germany || countryDoingAmphibiousAssault == MapInfo.CountryID.Italy)
            {
                if (!GetForcePoolForCountry(MapInfo.CountryID.Germany).GetBeachhead())
                    return false;
                regionStateToPlaceBeachHead.BeachHead = true;
                regionStateToPlaceBeachHead.BeachHeadCountry = MapInfo.CountryID.Germany;
            }
            else if(countryDoingAmphibiousAssault == MapInfo.CountryID.USSR)
            {
                if (!GetForcePoolForCountry(MapInfo.CountryID.USSR).GetBeachhead())
                    return false;
                regionStateToPlaceBeachHead.BeachHead = true;
                regionStateToPlaceBeachHead.BeachHeadCountry = MapInfo.CountryID.USSR;
            }
            else
            {
                if (!GetForcePoolForCountry(MapInfo.CountryID.GreatBritain).GetBeachhead())
                    return false;
                regionStateToPlaceBeachHead.BeachHead = true;
                regionStateToPlaceBeachHead.BeachHeadCountry = MapInfo.CountryID.GreatBritain;
            }

            return true;
        }

        public int GetNumBeachHeads(MapInfo.CountryID country)
        {
            return GetForcePoolForCountry(country).CurrentBeachHeads;
        }

        public void RemoveBeachHead(MapInfo.RegionID regionToRemoveFrom)
        {
            LandRegionState regionStateToRemoveBeachHead = (LandRegionState)GetRegionState(regionToRemoveFrom);
            if(regionStateToRemoveBeachHead.BeachHead)
            {
                regionStateToRemoveBeachHead.BeachHead = false;
                switch(regionStateToRemoveBeachHead.BeachHeadCountry)
                {
                    case MapInfo.CountryID.France:
                        GetForcePoolForCountry(MapInfo.CountryID.France).ReturnBeachHead();
                        break;
                    case MapInfo.CountryID.Germany:
                        GetForcePoolForCountry(MapInfo.CountryID.Germany).ReturnBeachHead();
                        break;
                    case MapInfo.CountryID.USSR:
                        GetForcePoolForCountry(MapInfo.CountryID.USSR).ReturnBeachHead();
                        break;
                    case MapInfo.CountryID.GreatBritain:
                        GetForcePoolForCountry(MapInfo.CountryID.GreatBritain).ReturnBeachHead();
                        break;
                    default:
                        throw new InvalidOperationException();
                }
            }
            else
            {
                throw new InvalidOperationException();
            }
        }

        public Weather GetCurrentWeatherAtRegion(MapInfo.RegionID region)
        {
            Region weatherRegion = MapInfo.GetRegion(region);
            if(weatherRegion.IsLandRegion())
            {
                LandRegion landWeatherRegion = weatherRegion as LandRegion;
                switch(landWeatherRegion.WeatherZone)
                {
                    case MapInfo.weatherZone.westernZone:
                        return currentWesternZoneWeather;
                    case MapInfo.weatherZone.southernZone:
                        return currentSouthernZoneWeather;
                    case MapInfo.weatherZone.easternZone:
                        return currentEasternZoneWeather;
                    default:
                        return Weather.Clear;
                }
            }
            else
            {
                throw new InvalidOperationException();
            }
        }

        public void ResetStratMoves()
        {
            numFrenchStratMoves = 2;
            numBritishStratMoves = 4;
            numUSStratMoves = 4;
            if (IsAxisCountry(GetRegionCountryControl(MapInfo.RegionID.Moscow)))
                numUSSRStratMoves = 1;
            else
                numUSSRStratMoves = 5;
            numGermanStratMoves = 7;
            numItalianStratMoves = 2;
            stratWarfareEffectOnGermanStratMoves = 0;
            stratWarfareEffectOnWAlliesStratMoves = 0;
            operationOverlordEffectOnGermanStratMoves = 0;
        }

        public void SetAllStratMoveAllowancesToZero()
        {
            numFrenchStratMoves = 0;
            numBritishStratMoves = 0;
            numUSStratMoves = 0;
            numUSSRStratMoves = 0;
            numGermanStratMoves = 0;
            numItalianStratMoves = 0;
        }

        public void SetAllAlliedStratMoveAllowancesToZero()
        {
            numFrenchStratMoves = 0;
            numBritishStratMoves = 0;
            numUSStratMoves = 0;
            numUSSRStratMoves = 0;
        }

        public void SetAllAxisStratMovesToZero()
        {
            numGermanStratMoves = 0;
            numItalianStratMoves = 0;
        }

        public void ResetStratMoveForCountry(MapInfo.CountryID country)
        {
            switch(country)
            {
                case MapInfo.CountryID.France:
                    numFrenchStratMoves = 2;
                    break;
                case MapInfo.CountryID.GreatBritain:
                    numBritishStratMoves = 4 - stratWarfareEffectOnWAlliesStratMoves;
                    if (numBritishStratMoves < 0)
                        numBritishStratMoves = 0;
                    break;
                case MapInfo.CountryID.USA:
                    numUSStratMoves = 4 - stratWarfareEffectOnWAlliesStratMoves;
                    if (numUSStratMoves < 0)
                        numUSStratMoves = 0;
                    break;
                case MapInfo.CountryID.USSR:
                    if (IsAxisCountry(GetRegionCountryControl(MapInfo.RegionID.Moscow)))
                        numUSSRStratMoves = 1;
                    else
                        numUSSRStratMoves = 5;
                    break;
                case MapInfo.CountryID.Germany:
                    numGermanStratMoves = 7 - stratWarfareEffectOnGermanStratMoves;
                    break;
                case MapInfo.CountryID.Italy:
                    numItalianStratMoves = 2;
                    break;
                default:
                    throw new InvalidOperationException();
            }
        }

        public int GetNumStratMovesForCountry(MapInfo.CountryID country)
        {
            switch (country)
            {
                case MapInfo.CountryID.France:
                    return numFrenchStratMoves;
                case MapInfo.CountryID.GreatBritain:
                    return numBritishStratMoves;
                case MapInfo.CountryID.USA:
                    return numUSStratMoves;
                case MapInfo.CountryID.USSR:
                    return numUSSRStratMoves;
                case MapInfo.CountryID.Germany:
                    return numGermanStratMoves;
                case MapInfo.CountryID.Italy:
                    return numItalianStratMoves;
                default:
                    throw new InvalidOperationException();
            }
        }

        public bool SpendStratMoveForCountry(MapInfo.CountryID country)
        {
            switch (country)
            {
                case MapInfo.CountryID.France:
                    if (numFrenchStratMoves > 0)
                        numFrenchStratMoves--;
                    else
                        return false;
                    break;
                case MapInfo.CountryID.GreatBritain:
                    if (numBritishStratMoves > 0)
                        numBritishStratMoves--;
                    else
                        return false;
                    break;
                case MapInfo.CountryID.USA:
                    if (numUSStratMoves > 0)
                        numUSStratMoves--;
                    else
                        return false;
                    break;
                case MapInfo.CountryID.USSR:
                    if (numUSSRStratMoves > 0)
                        numUSSRStratMoves--;
                    else
                        return false;
                    break;
                case MapInfo.CountryID.Germany:
                    if(numGermanStratMoves > 0)
                        numGermanStratMoves--;
                    else
                        return false;
                    break;
                case MapInfo.CountryID.Italy:
                    if (numItalianStratMoves > 0)
                        numItalianStratMoves = 2;
                    else
                        return false;
                    break;
                default:
                    throw new InvalidOperationException();
            }

            return true;
        }

        public void RemoveAllUnitsOfCountry(MapInfo.CountryID countryID)
        {
            System.Collections.IEnumerator regionStates = GetRegionStates();
            while (regionStates.MoveNext())
            {
                if (MapInfo.IsLandRegion(((RegionState)regionStates.Current).RegionID))
                {
                    LandRegionState landRegionState = (LandRegionState)regionStates.Current;
                    landRegionState.RemoveAllUnitsOfCountry(this, countryID);
                }
            }
        }

        public void FlipAllFleetPointCountersToAvailable()
        {
            System.Collections.IEnumerator regionStates = GetRegionStates();
            while (regionStates.MoveNext())
            {
                if (MapInfo.IsSeaRegion(((RegionState)regionStates.Current).RegionID))
                {
                    SeaRegionState seaRegionState = (SeaRegionState)regionStates.Current;
                    seaRegionState.FlipAllFleetsToTransportsAvailable();
                }
            }
        }

        public void RemoveGSUAndBeachheadsAloneWithEnemyBlocks()
        {
            System.Collections.IEnumerator regionStates = GetRegionStates();
            while (regionStates.MoveNext())
            {
                if(MapInfo.IsLandRegion(((RegionState)regionStates.Current).RegionID))
                {
                    LandRegionState landRegionState = (LandRegionState)regionStates.Current;
                    landRegionState.RemoveGSUAndBeachHeadsAloneWithGroundUnits(this);
                }
            }
        }

        private void DoFortressControlSwitch(LandRegionState fortressRegionState, LandRegionState soroundingRegionState)
        {
            if(!fortressRegionState.AnyAlliedBlocksRemaining(this))
            {
                if(soroundingRegionState.AnyAxisBlocksRemaining(this) && !soroundingRegionState.AnyAlliedBlocksRemaining(this))
                {
                    fortressRegionState.CountryControl = soroundingRegionState.GetBlockAt(0).CountryOwner;
                }
            }
            else if(!fortressRegionState.AnyAxisBlocksRemaining(this))
            {
                if (soroundingRegionState.AnyAlliedBlocksRemaining(this) && !soroundingRegionState.AnyAxisBlocksRemaining(this))
                {
                    fortressRegionState.CountryControl = soroundingRegionState.GetBlockAt(0).CountryOwner;
                }
            }
        }

        public void SwitchFortressControlAccordingToSorroundingRegion()
        {
            DoFortressControlSwitch((LandRegionState)GetRegionState(MapInfo.RegionID.Leningrad), (LandRegionState)GetRegionState(MapInfo.RegionID.Novgorod));
            DoFortressControlSwitch((LandRegionState)GetRegionState(MapInfo.RegionID.Sevastopol), (LandRegionState)GetRegionState(MapInfo.RegionID.Crimea));
            DoFortressControlSwitch((LandRegionState)GetRegionState(MapInfo.RegionID.Tobruk), (LandRegionState)GetRegionState(MapInfo.RegionID.Marmarica));
            DoFortressControlSwitch((LandRegionState)GetRegionState(MapInfo.RegionID.Gibraltar), (LandRegionState)GetRegionState(MapInfo.RegionID.Andalucia));
        }

        public void RemoveFieldFortificationsInContestedOrAlone()
        {
            System.Collections.IEnumerator regionStates = GetRegionStates();
            while (regionStates.MoveNext())
            {
                if (MapInfo.IsLandRegion(((RegionState)regionStates.Current).RegionID))
                {
                    LandRegionState landRegionState = (LandRegionState)regionStates.Current;
                    if(landRegionState.FortLevel == LandRegionState.FieldFortificationLevel.fieldfortification)
                    {
                        if (landRegionState.GetBlockAt(0) == null)
                            landRegionState.FortLevel = LandRegionState.FieldFortificationLevel.none;
                        else if (landRegionState.IsContested(this))
                            landRegionState.FortLevel = LandRegionState.FieldFortificationLevel.none;
                    }
                }
            }
        }

        public MapInfo.CountryID GetRegionCountryControl(MapInfo.RegionID regionID)
        {
            LandRegionState landRegionState = (LandRegionState)GetRegionState(regionID);

            return landRegionState.CountryControl;
        }

        public void RebuildMinorPowerSpecialActions()
        {
            if (IsNationAtWar(MapInfo.CountryID.Poland))
                BuildSpecialAction(MapInfo.CountryID.Poland);
            if (IsNationAtWar(MapInfo.CountryID.Spain))
                BuildSpecialAction(MapInfo.CountryID.Spain);
            if (IsNationAtWar(MapInfo.CountryID.Turkey))
                BuildSpecialAction(MapInfo.CountryID.Turkey);
            if (IsNationAtWar(MapInfo.CountryID.Yugoslavia))
                BuildSpecialAction(MapInfo.CountryID.Yugoslavia);
        }
    }
}
